diff --git a/[refs] b/[refs] index 023d9ea2ff82..63cc17f5ac0a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6e17e8b9fb74b9fb9f6ea331f7f4a049c5b4c4b8 +refs/heads/master: 282a39546f6d213399b325ec830ee37e8d915924 diff --git a/trunk/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt b/trunk/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt index b151fb1ddef0..8447fd7090d0 100644 --- a/trunk/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt +++ b/trunk/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt @@ -178,12 +178,3 @@ External interrupts: external irq3: interrupts = <1 3 n>; 'n' is sense (0: level high, 1: edge rising, 2: edge falling 3: level low) -fsl,mpc5200-mscan nodes ------------------------ -In addition to the required compatible-, reg- and interrupt-properites, you can -also specify which clock shall be used for the bus: - -- fsl,mscan-clk-src - a string describing the clock source. Valid values - are "ip" for IP_CLK and "sys" for SYS_XTAL. - "sys" is the default in case the property is not - present. diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 7f2f29cf75ff..e1cf7314a24c 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -3655,7 +3655,6 @@ L: netdev@vger.kernel.org W: http://www.linuxfoundation.org/en/Net W: http://patchwork.ozlabs.org/project/netdev/list/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6.git S: Maintained F: net/ F: include/net/ @@ -4303,7 +4302,6 @@ F: drivers/video/aty/aty128fb.c RALINK RT2X00 WIRELESS LAN DRIVER P: rt2x00 project -M: Ivo van Doorn L: linux-wireless@vger.kernel.org L: users@rt2x00.serialmonkey.com (moderated for non-subscribers) W: http://rt2x00.serialmonkey.com/ diff --git a/trunk/arch/alpha/include/asm/unistd.h b/trunk/arch/alpha/include/asm/unistd.h index 7f23665122df..5b5c17485942 100644 --- a/trunk/arch/alpha/include/asm/unistd.h +++ b/trunk/arch/alpha/include/asm/unistd.h @@ -433,11 +433,10 @@ #define __NR_signalfd 476 #define __NR_timerfd 477 #define __NR_eventfd 478 -#define __NR_recvmmsg 479 #ifdef __KERNEL__ -#define NR_SYSCALLS 480 +#define NR_SYSCALLS 479 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/trunk/arch/s390/appldata/appldata_net_sum.c b/trunk/arch/s390/appldata/appldata_net_sum.c index 4ce7fa95880f..fa741f84c5b9 100644 --- a/trunk/arch/s390/appldata/appldata_net_sum.c +++ b/trunk/arch/s390/appldata/appldata_net_sum.c @@ -83,9 +83,8 @@ static void appldata_get_net_sum_data(void *data) rx_dropped = 0; tx_dropped = 0; collisions = 0; - - rcu_read_lock(); - for_each_netdev_rcu(&init_net, dev) { + read_lock(&dev_base_lock); + for_each_netdev(&init_net, dev) { const struct net_device_stats *stats = dev_get_stats(dev); rx_packets += stats->rx_packets; @@ -99,8 +98,7 @@ static void appldata_get_net_sum_data(void *data) collisions += stats->collisions; i++; } - rcu_read_unlock(); - + read_unlock(&dev_base_lock); net_data->nr_interfaces = i; net_data->rx_packets = rx_packets; net_data->tx_packets = tx_packets; diff --git a/trunk/drivers/atm/ambassador.c b/trunk/drivers/atm/ambassador.c index 8af23411743c..66e181345b3a 100644 --- a/trunk/drivers/atm/ambassador.c +++ b/trunk/drivers/atm/ambassador.c @@ -2351,7 +2351,6 @@ static void __init amb_check_args (void) { MODULE_AUTHOR(maintainer_string); MODULE_DESCRIPTION(description_string); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("atmsar11.fw"); module_param(debug, ushort, 0644); module_param(cmds, uint, 0); module_param(txs, uint, 0); diff --git a/trunk/drivers/atm/solos-pci.c b/trunk/drivers/atm/solos-pci.c index d7ad19d2603a..c5f5186d62a3 100644 --- a/trunk/drivers/atm/solos-pci.c +++ b/trunk/drivers/atm/solos-pci.c @@ -142,9 +142,6 @@ MODULE_AUTHOR("Traverse Technologies "); MODULE_DESCRIPTION("Solos PCI driver"); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("solos-FPGA.bin"); -MODULE_FIRMWARE("solos-Firmware.bin"); -MODULE_FIRMWARE("solos-db-FPGA.bin"); MODULE_PARM_DESC(reset, "Reset Solos chips on startup"); MODULE_PARM_DESC(atmdebug, "Print ATM data"); MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade"); diff --git a/trunk/drivers/isdn/hardware/eicon/maintidi.c b/trunk/drivers/isdn/hardware/eicon/maintidi.c index 41c26e756452..23960cb6eaab 100644 --- a/trunk/drivers/isdn/hardware/eicon/maintidi.c +++ b/trunk/drivers/isdn/hardware/eicon/maintidi.c @@ -959,9 +959,8 @@ static int process_idi_event (diva_strace_context_t* pLib, } if (!strncmp("State\\Layer2 No1", path, pVar->path_length)) { char* tmp = &pLib->lines[0].pInterface->Layer2[0]; - dword l2_state; - if (diva_strace_read_uint(pVar, &l2_state)) - return -1; + dword l2_state; + diva_strace_read_uint (pVar, &l2_state); switch (l2_state) { case 0: diff --git a/trunk/drivers/isdn/hardware/eicon/message.c b/trunk/drivers/isdn/hardware/eicon/message.c index ae89fb89da64..27d5dd68f4fb 100644 --- a/trunk/drivers/isdn/hardware/eicon/message.c +++ b/trunk/drivers/isdn/hardware/eicon/message.c @@ -2692,7 +2692,7 @@ static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS) || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)) { - len = offsetof(T30_INFO, universal_6); + len = (byte)(&(((T30_INFO *) 0)->universal_6)); fax_info_change = false; if (ncpi->length >= 4) { @@ -2754,7 +2754,7 @@ static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, for (i = 0; i < w; i++) ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i]; ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0; - len = offsetof(T30_INFO, station_id) + 20; + len = (byte)(((T30_INFO *) 0)->station_id + 20); w = fax_parms[5].length; if (w > 20) w = 20; @@ -2788,7 +2788,7 @@ static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, } else { - len = offsetof(T30_INFO, universal_6); + len = (byte)(&(((T30_INFO *) 0)->universal_6)); } fax_info_change = true; @@ -2892,7 +2892,7 @@ static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF) && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)) { - len = offsetof(T30_INFO, station_id) + 20; + len = ((byte)(((T30_INFO *) 0)->station_id + 20)); if (plci->fax_connect_info_length < len) { ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0; @@ -3802,7 +3802,7 @@ static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, break; } ncpi = &m_parms[1]; - len = offsetof(T30_INFO, station_id) + 20; + len = ((byte)(((T30_INFO *) 0)->station_id + 20)); if (plci->fax_connect_info_length < len) { ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0; @@ -6844,7 +6844,7 @@ static void nl_ind(PLCI *plci) if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1]) & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD))) { - i = offsetof(T30_INFO, station_id) + 20 + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len; + i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len; while (i < plci->NL.RBuffer->length) plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++]; } @@ -7236,7 +7236,7 @@ static void nl_ind(PLCI *plci) { plci->RData[1].P = plci->RData[0].P; plci->RData[1].PLength = plci->RData[0].PLength; - plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3); + plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3); if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1)) plci->RData[0].PLength = 1; else @@ -8473,7 +8473,7 @@ static word add_b23(PLCI *plci, API_PARSE *bp) fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING; } len = nlc[0]; - pos = offsetof(T30_INFO, station_id) + 20; + pos = ((byte)(((T30_INFO *) 0)->station_id + 20)); if (pos < plci->fax_connect_info_length) { for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--) @@ -8525,7 +8525,7 @@ static word add_b23(PLCI *plci, API_PARSE *bp) } PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits); - len = offsetof(T30_INFO, station_id) + 20; + len = ((byte)(((T30_INFO *) 0)->station_id + 20)); for (i = 0; i < len; i++) plci->fax_connect_info_buffer[i] = nlc[1+i]; ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0; diff --git a/trunk/drivers/isdn/hardware/mISDN/speedfax.c b/trunk/drivers/isdn/hardware/mISDN/speedfax.c index 7726afdbb40b..ff3a4e290da3 100644 --- a/trunk/drivers/isdn/hardware/mISDN/speedfax.c +++ b/trunk/drivers/isdn/hardware/mISDN/speedfax.c @@ -110,7 +110,6 @@ set_debug(const char *val, struct kernel_param *kp) MODULE_AUTHOR("Karsten Keil"); MODULE_LICENSE("GPL v2"); MODULE_VERSION(SPEEDFAX_REV); -MODULE_FIRMWARE("isdn/ISAR.BIN"); module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Speedfax debug mask"); module_param(irqloops, uint, S_IRUGO | S_IWUSR); diff --git a/trunk/drivers/isdn/hisax/amd7930_fn.c b/trunk/drivers/isdn/hisax/amd7930_fn.c index d6fdf1f66754..bf526a7a63af 100644 --- a/trunk/drivers/isdn/hisax/amd7930_fn.c +++ b/trunk/drivers/isdn/hisax/amd7930_fn.c @@ -594,7 +594,6 @@ Amd7930_l1hw(struct PStack *st, int pr, void *arg) if (cs->debug & L1_DEB_WARN) debugl1(cs, "Amd7930: l1hw: l2l1 tx_skb exist this shouldn't happen"); skb_queue_tail(&cs->sq, skb); - spin_unlock_irqrestore(&cs->lock, flags); break; } if (cs->debug & DEB_DLOG_HEX) diff --git a/trunk/drivers/isdn/hisax/diva.c b/trunk/drivers/isdn/hisax/diva.c index 0b0c2e5d806b..018bd293e580 100644 --- a/trunk/drivers/isdn/hisax/diva.c +++ b/trunk/drivers/isdn/hisax/diva.c @@ -382,7 +382,7 @@ MemwaitforXFW(struct IsdnCardState *cs, int hscx) { int to = 50; - while (((MemReadHSCX(cs, hscx, HSCX_STAR) & 0x44) != 0x40) && to) { + while ((!(MemReadHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) { udelay(1); to--; } diff --git a/trunk/drivers/isdn/hisax/elsa_ser.c b/trunk/drivers/isdn/hisax/elsa_ser.c index 1657bba7879e..f181db464392 100644 --- a/trunk/drivers/isdn/hisax/elsa_ser.c +++ b/trunk/drivers/isdn/hisax/elsa_ser.c @@ -477,62 +477,62 @@ static void modem_set_init(struct IsdnCardState *cs) { int timeout; -#define RCV_DELAY 20 +#define RCV_DELAY 20000 modem_write_cmd(cs, MInit_1, strlen(MInit_1)); timeout = 1000; while(timeout-- && cs->hw.elsa.transcnt) udelay(1000); debugl1(cs, "msi tout=%d", timeout); - mdelay(RCV_DELAY); + udelay(RCV_DELAY); modem_write_cmd(cs, MInit_2, strlen(MInit_2)); timeout = 1000; while(timeout-- && cs->hw.elsa.transcnt) udelay(1000); debugl1(cs, "msi tout=%d", timeout); - mdelay(RCV_DELAY); + udelay(RCV_DELAY); modem_write_cmd(cs, MInit_3, strlen(MInit_3)); timeout = 1000; while(timeout-- && cs->hw.elsa.transcnt) udelay(1000); debugl1(cs, "msi tout=%d", timeout); - mdelay(RCV_DELAY); + udelay(RCV_DELAY); modem_write_cmd(cs, MInit_4, strlen(MInit_4)); timeout = 1000; while(timeout-- && cs->hw.elsa.transcnt) udelay(1000); debugl1(cs, "msi tout=%d", timeout); - mdelay(RCV_DELAY); + udelay(RCV_DELAY ); modem_write_cmd(cs, MInit_5, strlen(MInit_5)); timeout = 1000; while(timeout-- && cs->hw.elsa.transcnt) udelay(1000); debugl1(cs, "msi tout=%d", timeout); - mdelay(RCV_DELAY); + udelay(RCV_DELAY); modem_write_cmd(cs, MInit_6, strlen(MInit_6)); timeout = 1000; while(timeout-- && cs->hw.elsa.transcnt) udelay(1000); debugl1(cs, "msi tout=%d", timeout); - mdelay(RCV_DELAY); + udelay(RCV_DELAY); modem_write_cmd(cs, MInit_7, strlen(MInit_7)); timeout = 1000; while(timeout-- && cs->hw.elsa.transcnt) udelay(1000); debugl1(cs, "msi tout=%d", timeout); - mdelay(RCV_DELAY); + udelay(RCV_DELAY); } static void modem_set_dial(struct IsdnCardState *cs, int outgoing) { int timeout; -#define RCV_DELAY 20 +#define RCV_DELAY 20000 modem_write_cmd(cs, MInit_speed28800, strlen(MInit_speed28800)); timeout = 1000; while(timeout-- && cs->hw.elsa.transcnt) udelay(1000); debugl1(cs, "msi tout=%d", timeout); - mdelay(RCV_DELAY); + udelay(RCV_DELAY); if (outgoing) modem_write_cmd(cs, MInit_dialout, strlen(MInit_dialout)); else @@ -541,7 +541,7 @@ modem_set_dial(struct IsdnCardState *cs, int outgoing) { while(timeout-- && cs->hw.elsa.transcnt) udelay(1000); debugl1(cs, "msi tout=%d", timeout); - mdelay(RCV_DELAY); + udelay(RCV_DELAY); } static void diff --git a/trunk/drivers/isdn/hisax/hfc_usb.c b/trunk/drivers/isdn/hisax/hfc_usb.c index a420b64472e3..9de54202c90c 100644 --- a/trunk/drivers/isdn/hisax/hfc_usb.c +++ b/trunk/drivers/isdn/hisax/hfc_usb.c @@ -817,8 +817,8 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish) } /* we have a complete hdlc packet */ if (finish) { - if (fifo->skbuff->len > 3 && - !fifo->skbuff->data[fifo->skbuff->len - 1]) { + if ((!fifo->skbuff->data[fifo->skbuff->len - 1]) + && (fifo->skbuff->len > 3)) { if (fifon == HFCUSB_D_RX) { DBG(HFCUSB_DBG_DCHANNEL, diff --git a/trunk/drivers/isdn/hisax/hscx_irq.c b/trunk/drivers/isdn/hisax/hscx_irq.c index 2387d76c721a..7b1ad5e4ecda 100644 --- a/trunk/drivers/isdn/hisax/hscx_irq.c +++ b/trunk/drivers/isdn/hisax/hscx_irq.c @@ -32,7 +32,7 @@ waitforXFW(struct IsdnCardState *cs, int hscx) { int to = 50; - while (((READHSCX(cs, hscx, HSCX_STAR) & 0x44) != 0x40) && to) { + while ((!(READHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) { udelay(1); to--; } diff --git a/trunk/drivers/isdn/hisax/icc.c b/trunk/drivers/isdn/hisax/icc.c index c80cbb8a2ef9..9aba646ba221 100644 --- a/trunk/drivers/isdn/hisax/icc.c +++ b/trunk/drivers/isdn/hisax/icc.c @@ -468,7 +468,6 @@ ICC_l1hw(struct PStack *st, int pr, void *arg) if (cs->debug & L1_DEB_WARN) debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); skb_queue_tail(&cs->sq, skb); - spin_unlock_irqrestore(&cs->lock, flags); break; } if (cs->debug & DEB_DLOG_HEX) diff --git a/trunk/drivers/isdn/mISDN/socket.c b/trunk/drivers/isdn/mISDN/socket.c index fcfe17a19a61..28182ed8dea1 100644 --- a/trunk/drivers/isdn/mISDN/socket.c +++ b/trunk/drivers/isdn/mISDN/socket.c @@ -779,7 +779,7 @@ base_sock_create(struct net *net, struct socket *sock, int protocol) } static int -mISDN_sock_create(struct net *net, struct socket *sock, int proto, int kern) +mISDN_sock_create(struct net *net, struct socket *sock, int proto) { int err = -EPROTONOSUPPORT; diff --git a/trunk/drivers/isdn/mISDN/stack.c b/trunk/drivers/isdn/mISDN/stack.c index 0d05ec43012c..3e1532a180ff 100644 --- a/trunk/drivers/isdn/mISDN/stack.c +++ b/trunk/drivers/isdn/mISDN/stack.c @@ -364,7 +364,7 @@ add_layer2(struct mISDNchannel *ch, struct mISDNstack *st) static int st_own_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg) { - if (!ch->st || !ch->st->layer1) + if (!ch->st || ch->st->layer1) return -EINVAL; return ch->st->layer1->ctrl(ch->st->layer1, cmd, arg); } diff --git a/trunk/drivers/net/arm/w90p910_ether.c b/trunk/drivers/net/arm/w90p910_ether.c index b7f3866d546f..25e2627eb118 100644 --- a/trunk/drivers/net/arm/w90p910_ether.c +++ b/trunk/drivers/net/arm/w90p910_ether.c @@ -160,8 +160,8 @@ struct w90p910_ether { struct mii_if_info mii; struct timer_list check_timer; void __iomem *reg; - int rxirq; - int txirq; + unsigned int rxirq; + unsigned int txirq; unsigned int cur_tx; unsigned int cur_rx; unsigned int finish_tx; diff --git a/trunk/drivers/net/atl1c/atl1c.h b/trunk/drivers/net/atl1c/atl1c.h index a348a22551d9..2a1120ad2e74 100644 --- a/trunk/drivers/net/atl1c/atl1c.h +++ b/trunk/drivers/net/atl1c/atl1c.h @@ -470,28 +470,12 @@ struct atl1c_ring_header { struct atl1c_buffer { struct sk_buff *skb; /* socket buffer */ u16 length; /* rx buffer length */ - u16 flags; /* information of buffer */ -#define ATL1C_BUFFER_FREE 0x0001 -#define ATL1C_BUFFER_BUSY 0x0002 -#define ATL1C_BUFFER_STATE_MASK 0x0003 - -#define ATL1C_PCIMAP_SINGLE 0x0004 -#define ATL1C_PCIMAP_PAGE 0x0008 -#define ATL1C_PCIMAP_TYPE_MASK 0x000C - + u16 state; /* state of buffer */ +#define ATL1_BUFFER_FREE 0 +#define ATL1_BUFFER_BUSY 1 dma_addr_t dma; }; -#define ATL1C_SET_BUFFER_STATE(buff, state) do { \ - ((buff)->flags) &= ~ATL1C_BUFFER_STATE_MASK; \ - ((buff)->flags) |= (state); \ - } while (0) - -#define ATL1C_SET_PCIMAP_TYPE(buff, type) do { \ - ((buff)->flags) &= ~ATL1C_PCIMAP_TYPE_MASK; \ - ((buff)->flags) |= (type); \ - } while (0) - /* transimit packet descriptor (tpd) ring */ struct atl1c_tpd_ring { void *desc; /* descriptor ring virtual address */ diff --git a/trunk/drivers/net/atl1c/atl1c_main.c b/trunk/drivers/net/atl1c/atl1c_main.c index 5ef9e23435f4..3b8801a39726 100644 --- a/trunk/drivers/net/atl1c/atl1c_main.c +++ b/trunk/drivers/net/atl1c/atl1c_main.c @@ -710,29 +710,6 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) return 0; } -static inline void atl1c_clean_buffer(struct pci_dev *pdev, - struct atl1c_buffer *buffer_info, int in_irq) -{ - if (buffer_info->flags & ATL1C_BUFFER_FREE) - return; - if (buffer_info->dma) { - if (buffer_info->flags & ATL1C_PCIMAP_SINGLE) - pci_unmap_single(pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_TODEVICE); - else if (buffer_info->flags & ATL1C_PCIMAP_PAGE) - pci_unmap_page(pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_TODEVICE); - } - if (buffer_info->skb) { - if (in_irq) - dev_kfree_skb_irq(buffer_info->skb); - else - dev_kfree_skb(buffer_info->skb); - } - buffer_info->dma = 0; - buffer_info->skb = NULL; - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); -} /* * atl1c_clean_tx_ring - Free Tx-skb * @adapter: board private structure @@ -748,12 +725,22 @@ static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter, ring_count = tpd_ring->count; for (index = 0; index < ring_count; index++) { buffer_info = &tpd_ring->buffer_info[index]; - atl1c_clean_buffer(pdev, buffer_info, 0); + if (buffer_info->state == ATL1_BUFFER_FREE) + continue; + if (buffer_info->dma) + pci_unmap_single(pdev, buffer_info->dma, + buffer_info->length, + PCI_DMA_TODEVICE); + if (buffer_info->skb) + dev_kfree_skb(buffer_info->skb); + buffer_info->dma = 0; + buffer_info->skb = NULL; + buffer_info->state = ATL1_BUFFER_FREE; } /* Zero out Tx-buffers */ memset(tpd_ring->desc, 0, sizeof(struct atl1c_tpd_desc) * - ring_count); + ring_count); atomic_set(&tpd_ring->next_to_clean, 0); tpd_ring->next_to_use = 0; } @@ -773,7 +760,16 @@ static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter) for (i = 0; i < adapter->num_rx_queues; i++) { for (j = 0; j < rfd_ring[i].count; j++) { buffer_info = &rfd_ring[i].buffer_info[j]; - atl1c_clean_buffer(pdev, buffer_info, 0); + if (buffer_info->state == ATL1_BUFFER_FREE) + continue; + if (buffer_info->dma) + pci_unmap_single(pdev, buffer_info->dma, + buffer_info->length, + PCI_DMA_FROMDEVICE); + if (buffer_info->skb) + dev_kfree_skb(buffer_info->skb); + buffer_info->state = ATL1_BUFFER_FREE; + buffer_info->skb = NULL; } /* zero out the descriptor ring */ memset(rfd_ring[i].desc, 0, rfd_ring[i].size); @@ -800,8 +796,7 @@ static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) atomic_set(&tpd_ring[i].next_to_clean, 0); buffer_info = tpd_ring[i].buffer_info; for (j = 0; j < tpd_ring->count; j++) - ATL1C_SET_BUFFER_STATE(&buffer_info[i], - ATL1C_BUFFER_FREE); + buffer_info[i].state = ATL1_BUFFER_FREE; } for (i = 0; i < adapter->num_rx_queues; i++) { rfd_ring[i].next_to_use = 0; @@ -810,7 +805,7 @@ static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) rrd_ring[i].next_to_clean = 0; for (j = 0; j < rfd_ring[i].count; j++) { buffer_info = &rfd_ring[i].buffer_info[j]; - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); + buffer_info->state = ATL1_BUFFER_FREE; } } } @@ -1452,7 +1447,6 @@ static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter, struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *) &adapter->tpd_ring[type]; struct atl1c_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean); u16 hw_next_to_clean; u16 shift; @@ -1468,7 +1462,16 @@ static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter, while (next_to_clean != hw_next_to_clean) { buffer_info = &tpd_ring->buffer_info[next_to_clean]; - atl1c_clean_buffer(pdev, buffer_info, 1); + if (buffer_info->state == ATL1_BUFFER_BUSY) { + pci_unmap_page(adapter->pdev, buffer_info->dma, + buffer_info->length, PCI_DMA_TODEVICE); + buffer_info->dma = 0; + if (buffer_info->skb) { + dev_kfree_skb_irq(buffer_info->skb); + buffer_info->skb = NULL; + } + buffer_info->state = ATL1_BUFFER_FREE; + } if (++next_to_clean == tpd_ring->count) next_to_clean = 0; atomic_set(&tpd_ring->next_to_clean, next_to_clean); @@ -1584,7 +1587,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; next_info = &rfd_ring->buffer_info[next_next]; - while (next_info->flags & ATL1C_BUFFER_FREE) { + while (next_info->state == ATL1_BUFFER_FREE) { rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use); skb = dev_alloc_skb(adapter->rx_buffer_len); @@ -1600,13 +1603,12 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid * the 14 byte MAC header is removed */ vir_addr = skb->data; - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); + buffer_info->state = ATL1_BUFFER_BUSY; buffer_info->skb = skb; buffer_info->length = adapter->rx_buffer_len; buffer_info->dma = pci_map_single(pdev, vir_addr, buffer_info->length, PCI_DMA_FROMDEVICE); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE); rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); rfd_next_to_use = next_next; if (++next_next == rfd_ring->count) @@ -1651,8 +1653,7 @@ static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring, RRS_RX_RFD_INDEX_MASK; for (i = 0; i < num; i++) { buffer_info[rfd_index].skb = NULL; - ATL1C_SET_BUFFER_STATE(&buffer_info[rfd_index], - ATL1C_BUFFER_FREE); + buffer_info[rfd_index].state = ATL1_BUFFER_FREE; if (++rfd_index == rfd_ring->count) rfd_index = 0; } @@ -1966,8 +1967,7 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, buffer_info->length = map_len; buffer_info->dma = pci_map_single(adapter->pdev, skb->data, hdr_len, PCI_DMA_TODEVICE); - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE); + buffer_info->state = ATL1_BUFFER_BUSY; mapped_len += map_len; use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); use_tpd->buffer_len = cpu_to_le16(buffer_info->length); @@ -1987,8 +1987,8 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, buffer_info->dma = pci_map_single(adapter->pdev, skb->data + mapped_len, buffer_info->length, PCI_DMA_TODEVICE); - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE); + buffer_info->state = ATL1_BUFFER_BUSY; + use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); use_tpd->buffer_len = cpu_to_le16(buffer_info->length); } @@ -2008,8 +2008,8 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, frag->page_offset, buffer_info->length, PCI_DMA_TODEVICE); - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE); + buffer_info->state = ATL1_BUFFER_BUSY; + use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); use_tpd->buffer_len = cpu_to_le16(buffer_info->length); } diff --git a/trunk/drivers/net/benet/be.h b/trunk/drivers/net/benet/be.h index 67e165cf3f4e..ce7563175cef 100644 --- a/trunk/drivers/net/benet/be.h +++ b/trunk/drivers/net/benet/be.h @@ -269,8 +269,6 @@ struct be_adapter { u32 port_num; bool promiscuous; u32 cap; - u32 rx_fc; /* Rx flow control */ - u32 tx_fc; /* Tx flow control */ }; extern const struct ethtool_ops be_ethtool_ops; diff --git a/trunk/drivers/net/benet/be_cmds.h b/trunk/drivers/net/benet/be_cmds.h index 69dc017c814b..76410c1d5669 100644 --- a/trunk/drivers/net/benet/be_cmds.h +++ b/trunk/drivers/net/benet/be_cmds.h @@ -68,7 +68,7 @@ enum { #define CQE_STATUS_COMPL_MASK 0xFFFF #define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ #define CQE_STATUS_EXTD_MASK 0xFFFF -#define CQE_STATUS_EXTD_SHIFT 16 /* bits 16 - 31 */ +#define CQE_STATUS_EXTD_SHIFT 0 /* bits 0 - 15 */ struct be_mcc_compl { u32 status; /* dword 0 */ diff --git a/trunk/drivers/net/benet/be_ethtool.c b/trunk/drivers/net/benet/be_ethtool.c index e8f92831021a..edebce994906 100644 --- a/trunk/drivers/net/benet/be_ethtool.c +++ b/trunk/drivers/net/benet/be_ethtool.c @@ -362,12 +362,10 @@ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) if (ecmd->autoneg != 0) return -EINVAL; - adapter->tx_fc = ecmd->tx_pause; - adapter->rx_fc = ecmd->rx_pause; - status = be_cmd_set_flow_control(adapter, - adapter->tx_fc, adapter->rx_fc); - if (status) + status = be_cmd_set_flow_control(adapter, ecmd->tx_pause, + ecmd->rx_pause); + if (!status) dev_warn(&adapter->pdev->dev, "Pause param set failed.\n"); return status; diff --git a/trunk/drivers/net/benet/be_main.c b/trunk/drivers/net/benet/be_main.c index c0bd20356eaf..43180dc210a2 100644 --- a/trunk/drivers/net/benet/be_main.c +++ b/trunk/drivers/net/benet/be_main.c @@ -1611,21 +1611,11 @@ static int be_open(struct net_device *netdev) status = be_cmd_link_status_query(adapter, &link_up, &mac_speed, &link_speed); if (status) - goto ret_sts; + return status; be_link_status_update(adapter, link_up); - status = be_vid_config(adapter); - if (status) - goto ret_sts; - - status = be_cmd_set_flow_control(adapter, - adapter->tx_fc, adapter->rx_fc); - if (status) - goto ret_sts; - schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); -ret_sts: - return status; + return 0; } static int be_setup(struct be_adapter *adapter) @@ -1659,8 +1649,17 @@ static int be_setup(struct be_adapter *adapter) if (status != 0) goto rx_qs_destroy; + status = be_vid_config(adapter); + if (status != 0) + goto mccqs_destroy; + + status = be_cmd_set_flow_control(adapter, true, true); + if (status != 0) + goto mccqs_destroy; return 0; +mccqs_destroy: + be_mcc_queues_destroy(adapter); rx_qs_destroy: be_rx_queues_destroy(adapter); tx_qs_destroy: @@ -1911,10 +1910,6 @@ static void be_netdev_init(struct net_device *netdev) adapter->rx_csum = true; - /* Default settings for Rx and Tx flow control */ - adapter->rx_fc = true; - adapter->tx_fc = true; - netif_set_gso_max_size(netdev, 65535); BE_SET_NETDEV_OPS(netdev, &be_netdev_ops); @@ -2177,7 +2172,6 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) be_close(netdev); rtnl_unlock(); } - be_cmd_get_flow_control(adapter, &adapter->tx_fc, &adapter->rx_fc); be_clear(adapter); pci_save_state(pdev); diff --git a/trunk/drivers/net/bnx2x.h b/trunk/drivers/net/bnx2x.h index 928942b74ce6..c3b32f71e024 100644 --- a/trunk/drivers/net/bnx2x.h +++ b/trunk/drivers/net/bnx2x.h @@ -1191,7 +1191,7 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, #define MAX_SP_DESC_CNT (SP_DESC_CNT - 1) -#define BNX2X_BTR 1 +#define BNX2X_BTR 3 #define MAX_SPQ_PENDING 8 diff --git a/trunk/drivers/net/bnx2x_hsi.h b/trunk/drivers/net/bnx2x_hsi.h index 52585338ada8..dc2f8ed5fd07 100644 --- a/trunk/drivers/net/bnx2x_hsi.h +++ b/trunk/drivers/net/bnx2x_hsi.h @@ -264,7 +264,6 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101 0x00000800 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727 0x00000900 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC 0x00000a00 -#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823 0x00000b00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN 0x0000ff00 diff --git a/trunk/drivers/net/bnx2x_link.c b/trunk/drivers/net/bnx2x_link.c index 41b9b7bd3d8e..e32d3370862e 100644 --- a/trunk/drivers/net/bnx2x_link.c +++ b/trunk/drivers/net/bnx2x_link.c @@ -1107,21 +1107,18 @@ static void bnx2x_set_parallel_detection(struct link_params *params, MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL2, &control2); - if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) - control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN; - else - control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN; - DP(NETIF_MSG_LINK, "params->speed_cap_mask = 0x%x, control2 = 0x%x\n", - params->speed_cap_mask, control2); + + + control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN; + + CL45_WR_OVER_CL22(bp, params->port, params->phy_addr, MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL2, control2); - if ((phy_flags & PHY_XGXS_FLAG) && - (params->speed_cap_mask & - PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) { + if (phy_flags & PHY_XGXS_FLAG) { DP(NETIF_MSG_LINK, "XGXS\n"); CL45_WR_OVER_CL22(bp, params->port, @@ -1228,7 +1225,7 @@ static void bnx2x_set_autoneg(struct link_params *params, params->phy_addr, MDIO_REG_BANK_CL73_USERB0, MDIO_CL73_USERB0_CL73_UCTRL, - 0xe); + MDIO_CL73_USERB0_CL73_UCTRL_USTAT1_MUXSEL); /* Enable BAM Station Manager*/ CL45_WR_OVER_CL22(bp, params->port, @@ -1239,25 +1236,29 @@ static void bnx2x_set_autoneg(struct link_params *params, MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN | MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN); - /* Advertise CL73 link speeds */ + /* Merge CL73 and CL37 aneg resolution */ + CL45_RD_OVER_CL22(bp, params->port, + params->phy_addr, + MDIO_REG_BANK_CL73_USERB0, + MDIO_CL73_USERB0_CL73_BAM_CTRL3, + ®_val); + + if (params->speed_cap_mask & + PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) { + /* Set the CL73 AN speed */ CL45_RD_OVER_CL22(bp, params->port, params->phy_addr, MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV2, ®_val); - if (params->speed_cap_mask & - PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) - reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4; - if (params->speed_cap_mask & - PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) - reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX; CL45_WR_OVER_CL22(bp, params->port, params->phy_addr, MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV2, - reg_val); + reg_val | MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4); + } /* CL73 Autoneg Enabled */ reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN; @@ -1350,7 +1351,6 @@ static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params) static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u16 *ieee_fc) { - struct bnx2x *bp = params->bp; *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX; /* resolve pause mode and advertisement * Please refer to Table 28B-3 of the 802.3ab-1999 spec */ @@ -1380,30 +1380,18 @@ static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u16 *ieee_fc) *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE; break; } - DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc); } static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params, u16 ieee_fc) { struct bnx2x *bp = params->bp; - u16 val; /* for AN, we are always publishing full duplex */ CL45_WR_OVER_CL22(bp, params->port, params->phy_addr, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc); - CL45_RD_OVER_CL22(bp, params->port, - params->phy_addr, - MDIO_REG_BANK_CL73_IEEEB1, - MDIO_CL73_IEEEB1_AN_ADV1, &val); - val &= ~MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH; - val |= ((ieee_fc<<3) & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK); - CL45_WR_OVER_CL22(bp, params->port, - params->phy_addr, - MDIO_REG_BANK_CL73_IEEEB1, - MDIO_CL73_IEEEB1_AN_ADV1, val); } static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73) @@ -1621,39 +1609,6 @@ static u8 bnx2x_ext_phy_resolve_fc(struct link_params *params, return ret; } -static u8 bnx2x_direct_parallel_detect_used(struct link_params *params) -{ - struct bnx2x *bp = params->bp; - u16 pd_10g, status2_1000x; - CL45_RD_OVER_CL22(bp, params->port, - params->phy_addr, - MDIO_REG_BANK_SERDES_DIGITAL, - MDIO_SERDES_DIGITAL_A_1000X_STATUS2, - &status2_1000x); - CL45_RD_OVER_CL22(bp, params->port, - params->phy_addr, - MDIO_REG_BANK_SERDES_DIGITAL, - MDIO_SERDES_DIGITAL_A_1000X_STATUS2, - &status2_1000x); - if (status2_1000x & MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED) { - DP(NETIF_MSG_LINK, "1G parallel detect link on port %d\n", - params->port); - return 1; - } - - CL45_RD_OVER_CL22(bp, params->port, - params->phy_addr, - MDIO_REG_BANK_10G_PARALLEL_DETECT, - MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS, - &pd_10g); - - if (pd_10g & MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK) { - DP(NETIF_MSG_LINK, "10G parallel detect link on port %d\n", - params->port); - return 1; - } - return 0; -} static void bnx2x_flow_ctrl_resolve(struct link_params *params, struct link_vars *vars, @@ -1672,53 +1627,21 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params, (!(vars->phy_flags & PHY_SGMII_FLAG)) && (XGXS_EXT_PHY_TYPE(params->ext_phy_config) == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) { - if (bnx2x_direct_parallel_detect_used(params)) { - vars->flow_ctrl = params->req_fc_auto_adv; - return; - } - if ((gp_status & - (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | - MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) == - (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | - MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) { - - CL45_RD_OVER_CL22(bp, params->port, - params->phy_addr, - MDIO_REG_BANK_CL73_IEEEB1, - MDIO_CL73_IEEEB1_AN_ADV1, - &ld_pause); - CL45_RD_OVER_CL22(bp, params->port, - params->phy_addr, - MDIO_REG_BANK_CL73_IEEEB1, - MDIO_CL73_IEEEB1_AN_LP_ADV1, - &lp_pause); - pause_result = (ld_pause & - MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK) - >> 8; - pause_result |= (lp_pause & - MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK) - >> 10; - DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n", - pause_result); - } else { - - CL45_RD_OVER_CL22(bp, params->port, - params->phy_addr, - MDIO_REG_BANK_COMBO_IEEE0, - MDIO_COMBO_IEEE0_AUTO_NEG_ADV, - &ld_pause); - CL45_RD_OVER_CL22(bp, params->port, - params->phy_addr, - MDIO_REG_BANK_COMBO_IEEE0, - MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1, - &lp_pause); - pause_result = (ld_pause & + CL45_RD_OVER_CL22(bp, params->port, + params->phy_addr, + MDIO_REG_BANK_COMBO_IEEE0, + MDIO_COMBO_IEEE0_AUTO_NEG_ADV, + &ld_pause); + CL45_RD_OVER_CL22(bp, params->port, + params->phy_addr, + MDIO_REG_BANK_COMBO_IEEE0, + MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1, + &lp_pause); + pause_result = (ld_pause & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5; - pause_result |= (lp_pause & + pause_result |= (lp_pause & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7; - DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n", - pause_result); - } + DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result); bnx2x_pause_resolve(vars, pause_result); } else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) && (bnx2x_ext_phy_resolve_fc(params, vars))) { @@ -1929,8 +1852,6 @@ static u8 bnx2x_link_settings_status(struct link_params *params, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) || (XGXS_EXT_PHY_TYPE(params->ext_phy_config) == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) || - (XGXS_EXT_PHY_TYPE(params->ext_phy_config) == - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) || (XGXS_EXT_PHY_TYPE(params->ext_phy_config) == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726))) { vars->autoneg = AUTO_NEG_ENABLED; @@ -2066,7 +1987,8 @@ static u8 bnx2x_emac_program(struct link_params *params, GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE, mode); - bnx2x_set_led(params, LED_MODE_OPER, line_speed); + bnx2x_set_led(bp, params->port, LED_MODE_OPER, + line_speed, params->hw_led_mode, params->chip_id); return 0; } @@ -2200,8 +2122,6 @@ static void bnx2x_ext_phy_reset(struct link_params *params, MDIO_PMA_REG_CTRL, 1<<15); break; - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823: - break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE: DP(NETIF_MSG_LINK, "XGXS PHY Failure detected\n"); break; @@ -2592,11 +2512,16 @@ static void bnx2x_bcm8726_external_rom_boot(struct link_params *params) /* Need to wait 100ms after reset */ msleep(100); + /* Set serial boot control for external load */ + bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_MISC_CTRL1, 0x0001); + /* Micro controller re-boot */ bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, - 0x018B); + MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP); /* Set soft reset */ bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr, @@ -2604,10 +2529,14 @@ static void bnx2x_bcm8726_external_rom_boot(struct link_params *params) MDIO_PMA_REG_GEN_CTRL, MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET); + /* Set PLL register value to be same like in P13 ver */ bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD, - MDIO_PMA_REG_MISC_CTRL1, 0x0001); + MDIO_PMA_REG_PLL_CTRL, + 0x73A0); + /* Clear soft reset. + Will automatically reset micro-controller re-boot */ bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, @@ -3533,8 +3462,8 @@ static void bnx2x_8481_set_10G_led_mode(struct link_params *params, MDIO_PMA_REG_8481_LINK_SIGNAL, &val1); /* Set bit 2 to 0, and bits [1:0] to 10 */ - val1 &= ~((1<<0) | (1<<2) | (1<<7)); /* Clear bits 0,2,7*/ - val1 |= ((1<<1) | (1<<6)); /* Set bit 1, 6 */ + val1 &= ~((1<<0) | (1<<2)); /* Clear bits 0,2*/ + val1 |= (1<<1); /* Set bit 1 */ bnx2x_cl45_write(bp, params->port, ext_phy_type, @@ -3568,19 +3497,36 @@ static void bnx2x_8481_set_10G_led_mode(struct link_params *params, MDIO_PMA_REG_8481_LED2_MASK, 0); - /* Unmask LED3 for 10G link */ + /* LED3 (10G/1G/100/10G Activity) */ + bnx2x_cl45_read(bp, params->port, + ext_phy_type, + ext_phy_addr, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_8481_LINK_SIGNAL, + &val1); + /* Enable blink based on source 4(Activity) */ + val1 &= ~((1<<7) | (1<<8)); /* Clear bits 7,8 */ + val1 |= (1<<6); /* Set only bit 6 */ bnx2x_cl45_write(bp, params->port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD, + MDIO_PMA_REG_8481_LINK_SIGNAL, + val1); + + bnx2x_cl45_read(bp, params->port, + ext_phy_type, + ext_phy_addr, + MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, - 0x6); + &val1); + val1 |= (1<<4); /* Unmask LED3 for 10G link */ bnx2x_cl45_write(bp, params->port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD, - MDIO_PMA_REG_8481_LED3_BLINK, - 0); + MDIO_PMA_REG_8481_LED3_MASK, + val1); } @@ -3598,10 +3544,7 @@ static void bnx2x_init_internal_phy(struct link_params *params, bnx2x_set_preemphasis(params); /* forced speed requested? */ - if (vars->line_speed != SPEED_AUTO_NEG || - ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) == - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) && - params->loopback_mode == LOOPBACK_EXT)) { + if (vars->line_speed != SPEED_AUTO_NEG) { DP(NETIF_MSG_LINK, "not SGMII, no AN\n"); /* disable autoneg */ @@ -3750,6 +3693,19 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) } } /* Force speed */ + /* First enable LASI */ + bnx2x_cl45_write(bp, params->port, + ext_phy_type, + ext_phy_addr, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_RX_ALARM_CTRL, + 0x0400); + bnx2x_cl45_write(bp, params->port, + ext_phy_type, + ext_phy_addr, + MDIO_PMA_DEVAD, + MDIO_PMA_REG_LASI_CTRL, 0x0004); + if (params->req_line_speed == SPEED_10000) { DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n"); @@ -3759,9 +3715,6 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, 0x400); - bnx2x_cl45_write(bp, params->port, ext_phy_type, - ext_phy_addr, MDIO_PMA_DEVAD, - MDIO_PMA_REG_LASI_CTRL, 1); } else { /* Force 1Gbps using autoneg with 1G advertisment */ @@ -3803,17 +3756,6 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200); - bnx2x_cl45_write(bp, params->port, - ext_phy_type, - ext_phy_addr, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_RX_ALARM_CTRL, - 0x0400); - bnx2x_cl45_write(bp, params->port, - ext_phy_type, - ext_phy_addr, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_LASI_CTRL, 0x0004); } bnx2x_save_bcm_spirom_ver(bp, params->port, @@ -4349,7 +4291,6 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) break; } case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481: - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823: /* This phy uses the NIG latch mechanism since link indication arrives through its LED4 and not via its LASI signal, so we get steady signal @@ -4357,12 +4298,6 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4, 1 << NIG_LATCH_BC_ENABLE_MI_INT); - bnx2x_cl45_write(bp, params->port, - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481, - ext_phy_addr, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_CTRL, 0x0000); - bnx2x_8481_set_led4(params, ext_phy_type, ext_phy_addr); if (params->req_line_speed == SPEED_AUTO_NEG) { @@ -4459,12 +4394,17 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) { DP(NETIF_MSG_LINK, "Advertising 10G\n"); /* Restart autoneg for 10G*/ - + bnx2x_cl45_read(bp, params->port, + ext_phy_type, + ext_phy_addr, + MDIO_AN_DEVAD, + MDIO_AN_REG_CTRL, &val); + val |= 0x200; bnx2x_cl45_write(bp, params->port, ext_phy_type, ext_phy_addr, MDIO_AN_DEVAD, - MDIO_AN_REG_CTRL, 0x3200); + MDIO_AN_REG_CTRL, val); } } else { /* Force speed */ @@ -5208,7 +5148,6 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params, } break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481: - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823: /* Check 10G-BaseT link status */ /* Check PMD signal ok */ bnx2x_cl45_read(bp, params->port, ext_phy_type, @@ -5424,10 +5363,8 @@ static void bnx2x_link_int_ack(struct link_params *params, (NIG_STATUS_XGXS0_LINK10G | NIG_STATUS_XGXS0_LINK_STATUS | NIG_STATUS_SERDES0_LINK_STATUS)); - if ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) - == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481) || - (XGXS_EXT_PHY_TYPE(params->ext_phy_config) - == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823)) { + if (XGXS_EXT_PHY_TYPE(params->ext_phy_config) + == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481) { bnx2x_8481_rearm_latch_signal(bp, port, is_mi_int); } if (vars->phy_link_up) { @@ -5540,7 +5477,6 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, status = bnx2x_format_ver(spirom_ver, version, len); break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481: - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823: spirom_ver = ((spirom_ver & 0xF80) >> 7) << 16 | (spirom_ver & 0x7F); status = bnx2x_format_ver(spirom_ver, version, len); @@ -5792,15 +5728,13 @@ u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port, } -u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed) +u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed, + u16 hw_led_mode, u32 chip_id) { - u8 port = params->port; - u16 hw_led_mode = params->hw_led_mode; u8 rc = 0; u32 tmp; u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; - u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config); - struct bnx2x *bp = params->bp; + DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode); DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n", speed, hw_led_mode); @@ -5815,14 +5749,7 @@ u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed) break; case LED_MODE_OPER: - if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) { - REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0); - REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1); - } else { - REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, - hw_led_mode); - } - + REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode); REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + port*4, 0); /* Set blinking rate to ~15.9Hz */ @@ -5834,7 +5761,7 @@ u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed) EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp & (~EMAC_LED_OVERRIDE))); - if (CHIP_IS_E1(bp) && + if (!CHIP_IS_E1H(bp) && ((speed == SPEED_2500) || (speed == SPEED_1000) || (speed == SPEED_100) || @@ -5937,7 +5864,6 @@ static u8 bnx2x_link_initialize(struct link_params *params, if (non_ext_phy || (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) || - (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) || (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) || (params->loopback_mode == LOOPBACK_EXT_PHY)) { if (params->req_line_speed == SPEED_AUTO_NEG) @@ -6104,7 +6030,10 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); - bnx2x_set_led(params, LED_MODE_OPER, vars->line_speed); + bnx2x_set_led(bp, params->port, LED_MODE_OPER, + vars->line_speed, params->hw_led_mode, + params->chip_id); + } else /* No loopback */ { @@ -6162,13 +6091,15 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, { struct bnx2x *bp = params->bp; u32 ext_phy_config = params->ext_phy_config; + u16 hw_led_mode = params->hw_led_mode; + u32 chip_id = params->chip_id; u8 port = params->port; u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config); u32 val = REG_RD(bp, params->shmem_base + offsetof(struct shmem_region, dev_info. port_feature_config[params->port]. config)); - DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port); + /* disable attentions */ vars->link_status = 0; bnx2x_update_mng(params, vars->link_status); @@ -6196,7 +6127,7 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, * Hold it as vars low */ /* clear link led */ - bnx2x_set_led(params, LED_MODE_OFF, 0); + bnx2x_set_led(bp, port, LED_MODE_OFF, 0, hw_led_mode, chip_id); if (reset_ext_phy) { switch (ext_phy_type) { case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: @@ -6232,22 +6163,6 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, bnx2x_8726_reset_phy(bp, params->port, ext_phy_addr); break; } - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823: - { - u8 ext_phy_addr = - XGXS_EXT_PHY_ADDR(params->ext_phy_config); - bnx2x_cl45_write(bp, port, - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481, - ext_phy_addr, - MDIO_AN_DEVAD, - MDIO_AN_REG_CTRL, 0x0000); - bnx2x_cl45_write(bp, port, - PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481, - ext_phy_addr, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_CTRL, 1); - break; - } default: /* HW reset */ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, @@ -6283,7 +6198,9 @@ static u8 bnx2x_update_link_down(struct link_params *params, u8 port = params->port; DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port); - bnx2x_set_led(params, LED_MODE_OFF, 0); + bnx2x_set_led(bp, port, LED_MODE_OFF, + 0, params->hw_led_mode, + params->chip_id); /* indicate no mac active */ vars->mac_type = MAC_TYPE_NONE; @@ -6320,13 +6237,15 @@ static u8 bnx2x_update_link_up(struct link_params *params, vars->link_status |= LINK_STATUS_LINK_UP; if (link_10g) { bnx2x_bmac_enable(params, vars, 0); - bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000); + bnx2x_set_led(bp, port, LED_MODE_OPER, + SPEED_10000, params->hw_led_mode, + params->chip_id); + } else { + bnx2x_emac_enable(params, vars, 0); rc = bnx2x_emac_program(params, vars->line_speed, vars->duplex); - bnx2x_emac_enable(params, vars, 0); - /* AN complete? */ if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) { if (!(vars->phy_flags & @@ -6424,7 +6343,6 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) && (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) && - (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) && (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) && (ext_phy_link_up && !vars->phy_link_up)) bnx2x_init_internal_phy(params, vars, 0); @@ -6660,13 +6578,6 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base) return 0; } - -static u8 bnx2x_84823_common_init_phy(struct bnx2x *bp, u32 shmem_base) -{ - /* HW reset */ - bnx2x_ext_phy_hw_reset(bp, 1); - return 0; -} u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) { u8 rc = 0; @@ -6696,9 +6607,7 @@ u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) /* GPIO1 affects both ports, so there's need to pull it for single port alone */ rc = bnx2x_8726_common_init_phy(bp, shmem_base); - break; - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823: - rc = bnx2x_84823_common_init_phy(bp, shmem_base); + break; default: DP(NETIF_MSG_LINK, diff --git a/trunk/drivers/net/bnx2x_link.h b/trunk/drivers/net/bnx2x_link.h index 40c2981de8ed..f3e252264e1b 100644 --- a/trunk/drivers/net/bnx2x_link.h +++ b/trunk/drivers/net/bnx2x_link.h @@ -178,7 +178,8 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, Basically, the CLC takes care of the led for the link, but in case one needs to set/unset the led unnaturally, set the "mode" to LED_MODE_OPER to blink the led, and LED_MODE_OFF to set the led off.*/ -u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed); +u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed, + u16 hw_led_mode, u32 chip_id); #define LED_MODE_OFF 0 #define LED_MODE_OPER 2 diff --git a/trunk/drivers/net/bnx2x_main.c b/trunk/drivers/net/bnx2x_main.c index e2cf686d1118..59b58d8f0fa8 100644 --- a/trunk/drivers/net/bnx2x_main.c +++ b/trunk/drivers/net/bnx2x_main.c @@ -49,7 +49,6 @@ #include #include #include -#include #include "bnx2x.h" @@ -57,20 +56,15 @@ #include "bnx2x_init_ops.h" #include "bnx2x_dump.h" -#define DRV_MODULE_VERSION "1.52.1-4" -#define DRV_MODULE_RELDATE "2009/11/09" +#define DRV_MODULE_VERSION "1.52.1-1" +#define DRV_MODULE_RELDATE "2009/10/13" #define BNX2X_BC_VER 0x040200 #include #include "bnx2x_fw_file_hdr.h" /* FW files */ -#define FW_FILE_VERSION \ - __stringify(BCM_5710_FW_MAJOR_VERSION) "." \ - __stringify(BCM_5710_FW_MINOR_VERSION) "." \ - __stringify(BCM_5710_FW_REVISION_VERSION) "." \ - __stringify(BCM_5710_FW_ENGINEERING_VERSION) -#define FW_FILE_NAME_E1 "bnx2x-e1-" FW_FILE_VERSION ".fw" -#define FW_FILE_NAME_E1H "bnx2x-e1h-" FW_FILE_VERSION ".fw" +#define FW_FILE_PREFIX_E1 "bnx2x-e1-" +#define FW_FILE_PREFIX_E1H "bnx2x-e1h-" /* Time in jiffies before concluding the transmitter is hung */ #define TX_TIMEOUT (5*HZ) @@ -83,8 +77,6 @@ MODULE_AUTHOR("Eliezer Tamir"); MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710/57711/57711E Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); -MODULE_FIRMWARE(FW_FILE_NAME_E1); -MODULE_FIRMWARE(FW_FILE_NAME_E1H); static int multi_mode = 1; module_param(multi_mode, int, 0); @@ -4928,21 +4920,21 @@ static void bnx2x_update_coalesce(struct bnx2x *bp) REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_SB_HC_TIMEOUT_U_OFFSET(port, sb_id, U_SB_ETH_RX_CQ_INDEX), - bp->rx_ticks/(4 * BNX2X_BTR)); + bp->rx_ticks/12); REG_WR16(bp, BAR_CSTRORM_INTMEM + CSTORM_SB_HC_DISABLE_U_OFFSET(port, sb_id, U_SB_ETH_RX_CQ_INDEX), - (bp->rx_ticks/(4 * BNX2X_BTR)) ? 0 : 1); + (bp->rx_ticks/12) ? 0 : 1); /* HC_INDEX_C_ETH_TX_CQ_CONS */ REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_SB_HC_TIMEOUT_C_OFFSET(port, sb_id, C_SB_ETH_TX_CQ_INDEX), - bp->tx_ticks/(4 * BNX2X_BTR)); + bp->tx_ticks/12); REG_WR16(bp, BAR_CSTRORM_INTMEM + CSTORM_SB_HC_DISABLE_C_OFFSET(port, sb_id, C_SB_ETH_TX_CQ_INDEX), - (bp->tx_ticks/(4 * BNX2X_BTR)) ? 0 : 1); + (bp->tx_ticks/12) ? 0 : 1); } } @@ -7486,6 +7478,11 @@ static int bnx2x_set_int_mode(struct bnx2x *bp) rc = bnx2x_enable_msix(bp); if (rc) { /* failed to enable MSI-X */ + if (bp->multi_mode) + BNX2X_ERR("Multi requested but failed to " + "enable MSI-X (rx %d tx %d), " + "set number of queues to 1\n", + bp->num_rx_queues, bp->num_tx_queues); bp->num_rx_queues = 1; bp->num_tx_queues = 1; } @@ -9016,9 +9013,8 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) bp->rx_csum = 1; - /* make sure that the numbers are in the right granularity */ - bp->tx_ticks = (50 / (4 * BNX2X_BTR)) * (4 * BNX2X_BTR); - bp->rx_ticks = (25 / (4 * BNX2X_BTR)) * (4 * BNX2X_BTR); + bp->tx_ticks = 50; + bp->rx_ticks = 25; timer_interval = (CHIP_REV_IS_SLOW(bp) ? 5*HZ : HZ); bp->current_interval = (poll ? poll : timer_interval); @@ -10859,6 +10855,7 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev, static int bnx2x_phys_id(struct net_device *dev, u32 data) { struct bnx2x *bp = netdev_priv(dev); + int port = BP_PORT(bp); int i; if (!netif_running(dev)) @@ -10872,10 +10869,13 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data) for (i = 0; i < (data * 2); i++) { if ((i % 2) == 0) - bnx2x_set_led(&bp->link_params, LED_MODE_OPER, - SPEED_1000); + bnx2x_set_led(bp, port, LED_MODE_OPER, SPEED_1000, + bp->link_params.hw_led_mode, + bp->link_params.chip_id); else - bnx2x_set_led(&bp->link_params, LED_MODE_OFF, 0); + bnx2x_set_led(bp, port, LED_MODE_OFF, 0, + bp->link_params.hw_led_mode, + bp->link_params.chip_id); msleep_interruptible(500); if (signal_pending(current)) @@ -10883,8 +10883,10 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data) } if (bp->link_vars.link_up) - bnx2x_set_led(&bp->link_params, LED_MODE_OPER, - bp->link_vars.line_speed); + bnx2x_set_led(bp, port, LED_MODE_OPER, + bp->link_vars.line_speed, + bp->link_params.hw_led_mode, + bp->link_params.chip_id); return 0; } @@ -11125,10 +11127,10 @@ static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) } if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) - rc |= (XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP); + rc |= XMIT_GSO_V4; else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - rc |= (XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6); + rc |= XMIT_GSO_V6; return rc; } @@ -12115,14 +12117,21 @@ static inline void be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n) static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev) { - const char *fw_file_name; + char fw_file_name[40] = {0}; struct bnx2x_fw_file_hdr *fw_hdr; - int rc; + int rc, offset; + /* Create a FW file name */ if (CHIP_IS_E1(bp)) - fw_file_name = FW_FILE_NAME_E1; + offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1); else - fw_file_name = FW_FILE_NAME_E1H; + offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1H); + + sprintf(fw_file_name + offset, "%d.%d.%d.%d.fw", + BCM_5710_FW_MAJOR_VERSION, + BCM_5710_FW_MINOR_VERSION, + BCM_5710_FW_REVISION_VERSION, + BCM_5710_FW_ENGINEERING_VERSION); printk(KERN_INFO PFX "Loading %s\n", fw_file_name); diff --git a/trunk/drivers/net/bnx2x_reg.h b/trunk/drivers/net/bnx2x_reg.h index b668173ffcb4..aa76cbada5e2 100644 --- a/trunk/drivers/net/bnx2x_reg.h +++ b/trunk/drivers/net/bnx2x_reg.h @@ -4772,28 +4772,18 @@ #define PCI_ID_VAL2 0x438 -#define MDIO_REG_BANK_CL73_IEEEB0 0x0 -#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL 0x0 +#define MDIO_REG_BANK_CL73_IEEEB0 0x0 +#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL 0x0 #define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN 0x0200 #define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN 0x1000 #define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_MAIN_RST 0x8000 -#define MDIO_REG_BANK_CL73_IEEEB1 0x10 -#define MDIO_CL73_IEEEB1_AN_ADV1 0x00 -#define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE 0x0400 -#define MDIO_CL73_IEEEB1_AN_ADV1_ASYMMETRIC 0x0800 -#define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH 0x0C00 -#define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK 0x0C00 -#define MDIO_CL73_IEEEB1_AN_ADV2 0x01 +#define MDIO_REG_BANK_CL73_IEEEB1 0x10 +#define MDIO_CL73_IEEEB1_AN_ADV2 0x01 #define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M 0x0000 #define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX 0x0020 #define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 0x0040 #define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR 0x0080 -#define MDIO_CL73_IEEEB1_AN_LP_ADV1 0x03 -#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE 0x0400 -#define MDIO_CL73_IEEEB1_AN_LP_ADV1_ASYMMETRIC 0x0800 -#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_BOTH 0x0C00 -#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK 0x0C00 #define MDIO_REG_BANK_RX0 0x80b0 #define MDIO_RX0_RX_STATUS 0x10 @@ -4920,8 +4910,6 @@ #define MDIO_REG_BANK_10G_PARALLEL_DETECT 0x8130 -#define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS 0x10 -#define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK 0x8000 #define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL 0x11 #define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN 0x1 #define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK 0x13 @@ -4946,8 +4934,6 @@ #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_1G 0x0010 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_100M 0x0008 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_10M 0x0000 -#define MDIO_SERDES_DIGITAL_A_1000X_STATUS2 0x15 -#define MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED 0x0002 #define MDIO_SERDES_DIGITAL_MISC1 0x18 #define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_MASK 0xE000 #define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_25M 0x0000 @@ -5129,7 +5115,6 @@ Theotherbitsarereservedandshouldbezero*/ #define MDIO_PMA_REG_8481_LED1_MASK 0xa82c #define MDIO_PMA_REG_8481_LED2_MASK 0xa82f #define MDIO_PMA_REG_8481_LED3_MASK 0xa832 -#define MDIO_PMA_REG_8481_LED3_BLINK 0xa834 #define MDIO_PMA_REG_8481_SIGNAL_MASK 0xa835 #define MDIO_PMA_REG_8481_LINK_SIGNAL 0xa83b diff --git a/trunk/drivers/net/can/Kconfig b/trunk/drivers/net/can/Kconfig index c16e6ff139d0..26d77cc0ded7 100644 --- a/trunk/drivers/net/can/Kconfig +++ b/trunk/drivers/net/can/Kconfig @@ -102,31 +102,6 @@ config CAN_TI_HECC Driver for TI HECC (High End CAN Controller) module found on many TI devices. The device specifications are available from www.ti.com -config CAN_MCP251X - tristate "Microchip MCP251x SPI CAN controllers" - depends on CAN_DEV && SPI - ---help--- - Driver for the Microchip MCP251x SPI CAN controllers. - -config CAN_MSCAN - depends on CAN_DEV && (PPC || M68K || M68KNOMMU) - tristate "Support for Freescale MSCAN based chips" - ---help--- - The Motorola Scalable Controller Area Network (MSCAN) definition - is based on the MSCAN12 definition which is the specific - implementation of the Motorola Scalable CAN concept targeted for - the Motorola MC68HC12 Microcontroller Family. - -config CAN_MPC52XX - tristate "Freescale MPC5xxx onboard CAN controller" - depends on CAN_MSCAN && PPC_MPC52xx - ---help--- - If you say yes here you get support for Freescale's MPC52xx - onboard dualCAN controller. - - This driver can also be built as a module. If so, the module - will be called mpc5xxx_can. - config CAN_DEBUG_DEVICES bool "CAN devices debugging messages" depends on CAN diff --git a/trunk/drivers/net/can/Makefile b/trunk/drivers/net/can/Makefile index 56899fef1c6a..31f4ab5df28b 100644 --- a/trunk/drivers/net/can/Makefile +++ b/trunk/drivers/net/can/Makefile @@ -10,9 +10,7 @@ can-dev-y := dev.o obj-y += usb/ obj-$(CONFIG_CAN_SJA1000) += sja1000/ -obj-$(CONFIG_CAN_MSCAN) += mscan/ obj-$(CONFIG_CAN_AT91) += at91_can.o obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o -obj-$(CONFIG_CAN_MCP251X) += mcp251x.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/trunk/drivers/net/can/dev.c b/trunk/drivers/net/can/dev.c index 26c89aaeba62..c3db111d2ff5 100644 --- a/trunk/drivers/net/can/dev.c +++ b/trunk/drivers/net/can/dev.c @@ -637,22 +637,6 @@ static int can_changelink(struct net_device *dev, return 0; } -static size_t can_get_size(const struct net_device *dev) -{ - struct can_priv *priv = netdev_priv(dev); - size_t size; - - size = nla_total_size(sizeof(u32)); /* IFLA_CAN_STATE */ - size += sizeof(struct can_ctrlmode); /* IFLA_CAN_CTRLMODE */ - size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */ - size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */ - size += sizeof(struct can_clock); /* IFLA_CAN_CLOCK */ - if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */ - size += sizeof(struct can_bittiming_const); - - return size; -} - static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); @@ -690,7 +674,7 @@ static int can_fill_xstats(struct sk_buff *skb, const struct net_device *dev) return -EMSGSIZE; } -static int can_newlink(struct net *src_net, struct net_device *dev, +static int can_newlink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { return -EOPNOTSUPP; @@ -703,7 +687,6 @@ static struct rtnl_link_ops can_link_ops __read_mostly = { .setup = can_setup, .newlink = can_newlink, .changelink = can_changelink, - .get_size = can_get_size, .fill_info = can_fill_info, .fill_xstats = can_fill_xstats, }; diff --git a/trunk/drivers/net/can/mcp251x.c b/trunk/drivers/net/can/mcp251x.c deleted file mode 100644 index 8f48f4b50b7c..000000000000 --- a/trunk/drivers/net/can/mcp251x.c +++ /dev/null @@ -1,1164 +0,0 @@ -/* - * CAN bus driver for Microchip 251x CAN Controller with SPI Interface - * - * MCP2510 support and bug fixes by Christian Pellegrin - * - * - * Copyright 2009 Christian Pellegrin EVOL S.r.l. - * - * Copyright 2007 Raymarine UK, Ltd. All Rights Reserved. - * Written under contract by: - * Chris Elston, Katalix Systems, Ltd. - * - * Based on Microchip MCP251x CAN controller driver written by - * David Vrabel, Copyright 2006 Arcom Control Systems Ltd. - * - * Based on CAN bus driver for the CCAN controller written by - * - Sascha Hauer, Marc Kleine-Budde, Pengutronix - * - Simon Kallweit, intefo AG - * Copyright 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the version 2 of the GNU General Public License - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * - * Your platform definition file should specify something like: - * - * static struct mcp251x_platform_data mcp251x_info = { - * .oscillator_frequency = 8000000, - * .board_specific_setup = &mcp251x_setup, - * .model = CAN_MCP251X_MCP2510, - * .power_enable = mcp251x_power_enable, - * .transceiver_enable = NULL, - * }; - * - * static struct spi_board_info spi_board_info[] = { - * { - * .modalias = "mcp251x", - * .platform_data = &mcp251x_info, - * .irq = IRQ_EINT13, - * .max_speed_hz = 2*1000*1000, - * .chip_select = 2, - * }, - * }; - * - * Please see mcp251x.h for a description of the fields in - * struct mcp251x_platform_data. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* SPI interface instruction set */ -#define INSTRUCTION_WRITE 0x02 -#define INSTRUCTION_READ 0x03 -#define INSTRUCTION_BIT_MODIFY 0x05 -#define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n)) -#define INSTRUCTION_READ_RXB(n) (((n) == 0) ? 0x90 : 0x94) -#define INSTRUCTION_RESET 0xC0 - -/* MPC251x registers */ -#define CANSTAT 0x0e -#define CANCTRL 0x0f -# define CANCTRL_REQOP_MASK 0xe0 -# define CANCTRL_REQOP_CONF 0x80 -# define CANCTRL_REQOP_LISTEN_ONLY 0x60 -# define CANCTRL_REQOP_LOOPBACK 0x40 -# define CANCTRL_REQOP_SLEEP 0x20 -# define CANCTRL_REQOP_NORMAL 0x00 -# define CANCTRL_OSM 0x08 -# define CANCTRL_ABAT 0x10 -#define TEC 0x1c -#define REC 0x1d -#define CNF1 0x2a -# define CNF1_SJW_SHIFT 6 -#define CNF2 0x29 -# define CNF2_BTLMODE 0x80 -# define CNF2_SAM 0x40 -# define CNF2_PS1_SHIFT 3 -#define CNF3 0x28 -# define CNF3_SOF 0x08 -# define CNF3_WAKFIL 0x04 -# define CNF3_PHSEG2_MASK 0x07 -#define CANINTE 0x2b -# define CANINTE_MERRE 0x80 -# define CANINTE_WAKIE 0x40 -# define CANINTE_ERRIE 0x20 -# define CANINTE_TX2IE 0x10 -# define CANINTE_TX1IE 0x08 -# define CANINTE_TX0IE 0x04 -# define CANINTE_RX1IE 0x02 -# define CANINTE_RX0IE 0x01 -#define CANINTF 0x2c -# define CANINTF_MERRF 0x80 -# define CANINTF_WAKIF 0x40 -# define CANINTF_ERRIF 0x20 -# define CANINTF_TX2IF 0x10 -# define CANINTF_TX1IF 0x08 -# define CANINTF_TX0IF 0x04 -# define CANINTF_RX1IF 0x02 -# define CANINTF_RX0IF 0x01 -#define EFLG 0x2d -# define EFLG_EWARN 0x01 -# define EFLG_RXWAR 0x02 -# define EFLG_TXWAR 0x04 -# define EFLG_RXEP 0x08 -# define EFLG_TXEP 0x10 -# define EFLG_TXBO 0x20 -# define EFLG_RX0OVR 0x40 -# define EFLG_RX1OVR 0x80 -#define TXBCTRL(n) (((n) * 0x10) + 0x30 + TXBCTRL_OFF) -# define TXBCTRL_ABTF 0x40 -# define TXBCTRL_MLOA 0x20 -# define TXBCTRL_TXERR 0x10 -# define TXBCTRL_TXREQ 0x08 -#define TXBSIDH(n) (((n) * 0x10) + 0x30 + TXBSIDH_OFF) -# define SIDH_SHIFT 3 -#define TXBSIDL(n) (((n) * 0x10) + 0x30 + TXBSIDL_OFF) -# define SIDL_SID_MASK 7 -# define SIDL_SID_SHIFT 5 -# define SIDL_EXIDE_SHIFT 3 -# define SIDL_EID_SHIFT 16 -# define SIDL_EID_MASK 3 -#define TXBEID8(n) (((n) * 0x10) + 0x30 + TXBEID8_OFF) -#define TXBEID0(n) (((n) * 0x10) + 0x30 + TXBEID0_OFF) -#define TXBDLC(n) (((n) * 0x10) + 0x30 + TXBDLC_OFF) -# define DLC_RTR_SHIFT 6 -#define TXBCTRL_OFF 0 -#define TXBSIDH_OFF 1 -#define TXBSIDL_OFF 2 -#define TXBEID8_OFF 3 -#define TXBEID0_OFF 4 -#define TXBDLC_OFF 5 -#define TXBDAT_OFF 6 -#define RXBCTRL(n) (((n) * 0x10) + 0x60 + RXBCTRL_OFF) -# define RXBCTRL_BUKT 0x04 -# define RXBCTRL_RXM0 0x20 -# define RXBCTRL_RXM1 0x40 -#define RXBSIDH(n) (((n) * 0x10) + 0x60 + RXBSIDH_OFF) -# define RXBSIDH_SHIFT 3 -#define RXBSIDL(n) (((n) * 0x10) + 0x60 + RXBSIDL_OFF) -# define RXBSIDL_IDE 0x08 -# define RXBSIDL_EID 3 -# define RXBSIDL_SHIFT 5 -#define RXBEID8(n) (((n) * 0x10) + 0x60 + RXBEID8_OFF) -#define RXBEID0(n) (((n) * 0x10) + 0x60 + RXBEID0_OFF) -#define RXBDLC(n) (((n) * 0x10) + 0x60 + RXBDLC_OFF) -# define RXBDLC_LEN_MASK 0x0f -# define RXBDLC_RTR 0x40 -#define RXBCTRL_OFF 0 -#define RXBSIDH_OFF 1 -#define RXBSIDL_OFF 2 -#define RXBEID8_OFF 3 -#define RXBEID0_OFF 4 -#define RXBDLC_OFF 5 -#define RXBDAT_OFF 6 - -#define GET_BYTE(val, byte) \ - (((val) >> ((byte) * 8)) & 0xff) -#define SET_BYTE(val, byte) \ - (((val) & 0xff) << ((byte) * 8)) - -/* - * Buffer size required for the largest SPI transfer (i.e., reading a - * frame) - */ -#define CAN_FRAME_MAX_DATA_LEN 8 -#define SPI_TRANSFER_BUF_LEN (6 + CAN_FRAME_MAX_DATA_LEN) -#define CAN_FRAME_MAX_BITS 128 - -#define TX_ECHO_SKB_MAX 1 - -#define DEVICE_NAME "mcp251x" - -static int mcp251x_enable_dma; /* Enable SPI DMA. Default: 0 (Off) */ -module_param(mcp251x_enable_dma, int, S_IRUGO); -MODULE_PARM_DESC(mcp251x_enable_dma, "Enable SPI DMA. Default: 0 (Off)"); - -static struct can_bittiming_const mcp251x_bittiming_const = { - .name = DEVICE_NAME, - .tseg1_min = 3, - .tseg1_max = 16, - .tseg2_min = 2, - .tseg2_max = 8, - .sjw_max = 4, - .brp_min = 1, - .brp_max = 64, - .brp_inc = 1, -}; - -struct mcp251x_priv { - struct can_priv can; - struct net_device *net; - struct spi_device *spi; - - struct mutex spi_lock; /* SPI buffer lock */ - u8 *spi_tx_buf; - u8 *spi_rx_buf; - dma_addr_t spi_tx_dma; - dma_addr_t spi_rx_dma; - - struct sk_buff *tx_skb; - int tx_len; - struct workqueue_struct *wq; - struct work_struct tx_work; - struct work_struct irq_work; - struct completion awake; - int wake; - int force_quit; - int after_suspend; -#define AFTER_SUSPEND_UP 1 -#define AFTER_SUSPEND_DOWN 2 -#define AFTER_SUSPEND_POWER 4 -#define AFTER_SUSPEND_RESTART 8 - int restart_tx; -}; - -static void mcp251x_clean(struct net_device *net) -{ - struct mcp251x_priv *priv = netdev_priv(net); - - net->stats.tx_errors++; - if (priv->tx_skb) - dev_kfree_skb(priv->tx_skb); - if (priv->tx_len) - can_free_echo_skb(priv->net, 0); - priv->tx_skb = NULL; - priv->tx_len = 0; -} - -/* - * Note about handling of error return of mcp251x_spi_trans: accessing - * registers via SPI is not really different conceptually than using - * normal I/O assembler instructions, although it's much more - * complicated from a practical POV. So it's not advisable to always - * check the return value of this function. Imagine that every - * read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0) - * error();", it would be a great mess (well there are some situation - * when exception handling C++ like could be useful after all). So we - * just check that transfers are OK at the beginning of our - * conversation with the chip and to avoid doing really nasty things - * (like injecting bogus packets in the network stack). - */ -static int mcp251x_spi_trans(struct spi_device *spi, int len) -{ - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - struct spi_transfer t = { - .tx_buf = priv->spi_tx_buf, - .rx_buf = priv->spi_rx_buf, - .len = len, - .cs_change = 0, - }; - struct spi_message m; - int ret; - - spi_message_init(&m); - - if (mcp251x_enable_dma) { - t.tx_dma = priv->spi_tx_dma; - t.rx_dma = priv->spi_rx_dma; - m.is_dma_mapped = 1; - } - - spi_message_add_tail(&t, &m); - - ret = spi_sync(spi, &m); - if (ret) - dev_err(&spi->dev, "spi transfer failed: ret = %d\n", ret); - return ret; -} - -static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg) -{ - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - u8 val = 0; - - mutex_lock(&priv->spi_lock); - - priv->spi_tx_buf[0] = INSTRUCTION_READ; - priv->spi_tx_buf[1] = reg; - - mcp251x_spi_trans(spi, 3); - val = priv->spi_rx_buf[2]; - - mutex_unlock(&priv->spi_lock); - - return val; -} - -static void mcp251x_write_reg(struct spi_device *spi, u8 reg, uint8_t val) -{ - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - - mutex_lock(&priv->spi_lock); - - priv->spi_tx_buf[0] = INSTRUCTION_WRITE; - priv->spi_tx_buf[1] = reg; - priv->spi_tx_buf[2] = val; - - mcp251x_spi_trans(spi, 3); - - mutex_unlock(&priv->spi_lock); -} - -static void mcp251x_write_bits(struct spi_device *spi, u8 reg, - u8 mask, uint8_t val) -{ - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - - mutex_lock(&priv->spi_lock); - - priv->spi_tx_buf[0] = INSTRUCTION_BIT_MODIFY; - priv->spi_tx_buf[1] = reg; - priv->spi_tx_buf[2] = mask; - priv->spi_tx_buf[3] = val; - - mcp251x_spi_trans(spi, 4); - - mutex_unlock(&priv->spi_lock); -} - -static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, - int len, int tx_buf_idx) -{ - struct mcp251x_platform_data *pdata = spi->dev.platform_data; - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - - if (pdata->model == CAN_MCP251X_MCP2510) { - int i; - - for (i = 1; i < TXBDAT_OFF + len; i++) - mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx) + i, - buf[i]); - } else { - mutex_lock(&priv->spi_lock); - memcpy(priv->spi_tx_buf, buf, TXBDAT_OFF + len); - mcp251x_spi_trans(spi, TXBDAT_OFF + len); - mutex_unlock(&priv->spi_lock); - } -} - -static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, - int tx_buf_idx) -{ - u32 sid, eid, exide, rtr; - u8 buf[SPI_TRANSFER_BUF_LEN]; - - exide = (frame->can_id & CAN_EFF_FLAG) ? 1 : 0; /* Extended ID Enable */ - if (exide) - sid = (frame->can_id & CAN_EFF_MASK) >> 18; - else - sid = frame->can_id & CAN_SFF_MASK; /* Standard ID */ - eid = frame->can_id & CAN_EFF_MASK; /* Extended ID */ - rtr = (frame->can_id & CAN_RTR_FLAG) ? 1 : 0; /* Remote transmission */ - - buf[TXBCTRL_OFF] = INSTRUCTION_LOAD_TXB(tx_buf_idx); - buf[TXBSIDH_OFF] = sid >> SIDH_SHIFT; - buf[TXBSIDL_OFF] = ((sid & SIDL_SID_MASK) << SIDL_SID_SHIFT) | - (exide << SIDL_EXIDE_SHIFT) | - ((eid >> SIDL_EID_SHIFT) & SIDL_EID_MASK); - buf[TXBEID8_OFF] = GET_BYTE(eid, 1); - buf[TXBEID0_OFF] = GET_BYTE(eid, 0); - buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc; - memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc); - mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx); - mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ); -} - -static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, - int buf_idx) -{ - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - struct mcp251x_platform_data *pdata = spi->dev.platform_data; - - if (pdata->model == CAN_MCP251X_MCP2510) { - int i, len; - - for (i = 1; i < RXBDAT_OFF; i++) - buf[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i); - len = buf[RXBDLC_OFF] & RXBDLC_LEN_MASK; - if (len > 8) - len = 8; - for (; i < (RXBDAT_OFF + len); i++) - buf[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i); - } else { - mutex_lock(&priv->spi_lock); - - priv->spi_tx_buf[RXBCTRL_OFF] = INSTRUCTION_READ_RXB(buf_idx); - mcp251x_spi_trans(spi, SPI_TRANSFER_BUF_LEN); - memcpy(buf, priv->spi_rx_buf, SPI_TRANSFER_BUF_LEN); - - mutex_unlock(&priv->spi_lock); - } -} - -static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx) -{ - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - struct sk_buff *skb; - struct can_frame *frame; - u8 buf[SPI_TRANSFER_BUF_LEN]; - - skb = alloc_can_skb(priv->net, &frame); - if (!skb) { - dev_err(&spi->dev, "cannot allocate RX skb\n"); - priv->net->stats.rx_dropped++; - return; - } - - mcp251x_hw_rx_frame(spi, buf, buf_idx); - if (buf[RXBSIDL_OFF] & RXBSIDL_IDE) { - /* Extended ID format */ - frame->can_id = CAN_EFF_FLAG; - frame->can_id |= - /* Extended ID part */ - SET_BYTE(buf[RXBSIDL_OFF] & RXBSIDL_EID, 2) | - SET_BYTE(buf[RXBEID8_OFF], 1) | - SET_BYTE(buf[RXBEID0_OFF], 0) | - /* Standard ID part */ - (((buf[RXBSIDH_OFF] << RXBSIDH_SHIFT) | - (buf[RXBSIDL_OFF] >> RXBSIDL_SHIFT)) << 18); - /* Remote transmission request */ - if (buf[RXBDLC_OFF] & RXBDLC_RTR) - frame->can_id |= CAN_RTR_FLAG; - } else { - /* Standard ID format */ - frame->can_id = - (buf[RXBSIDH_OFF] << RXBSIDH_SHIFT) | - (buf[RXBSIDL_OFF] >> RXBSIDL_SHIFT); - } - /* Data length */ - frame->can_dlc = buf[RXBDLC_OFF] & RXBDLC_LEN_MASK; - if (frame->can_dlc > 8) { - dev_warn(&spi->dev, "invalid frame recevied\n"); - priv->net->stats.rx_errors++; - dev_kfree_skb(skb); - return; - } - memcpy(frame->data, buf + RXBDAT_OFF, frame->can_dlc); - - priv->net->stats.rx_packets++; - priv->net->stats.rx_bytes += frame->can_dlc; - netif_rx(skb); -} - -static void mcp251x_hw_sleep(struct spi_device *spi) -{ - mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP); -} - -static void mcp251x_hw_wakeup(struct spi_device *spi) -{ - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - - priv->wake = 1; - - /* Can only wake up by generating a wake-up interrupt. */ - mcp251x_write_bits(spi, CANINTE, CANINTE_WAKIE, CANINTE_WAKIE); - mcp251x_write_bits(spi, CANINTF, CANINTF_WAKIF, CANINTF_WAKIF); - - /* Wait until the device is awake */ - if (!wait_for_completion_timeout(&priv->awake, HZ)) - dev_err(&spi->dev, "MCP251x didn't wake-up\n"); -} - -static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb, - struct net_device *net) -{ - struct mcp251x_priv *priv = netdev_priv(net); - struct spi_device *spi = priv->spi; - - if (priv->tx_skb || priv->tx_len) { - dev_warn(&spi->dev, "hard_xmit called while tx busy\n"); - netif_stop_queue(net); - return NETDEV_TX_BUSY; - } - - if (skb->len != sizeof(struct can_frame)) { - dev_err(&spi->dev, "dropping packet - bad length\n"); - dev_kfree_skb(skb); - net->stats.tx_dropped++; - return NETDEV_TX_OK; - } - - netif_stop_queue(net); - priv->tx_skb = skb; - net->trans_start = jiffies; - queue_work(priv->wq, &priv->tx_work); - - return NETDEV_TX_OK; -} - -static int mcp251x_do_set_mode(struct net_device *net, enum can_mode mode) -{ - struct mcp251x_priv *priv = netdev_priv(net); - - switch (mode) { - case CAN_MODE_START: - /* We have to delay work since SPI I/O may sleep */ - priv->can.state = CAN_STATE_ERROR_ACTIVE; - priv->restart_tx = 1; - if (priv->can.restart_ms == 0) - priv->after_suspend = AFTER_SUSPEND_RESTART; - queue_work(priv->wq, &priv->irq_work); - break; - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static void mcp251x_set_normal_mode(struct spi_device *spi) -{ - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - unsigned long timeout; - - /* Enable interrupts */ - mcp251x_write_reg(spi, CANINTE, - CANINTE_ERRIE | CANINTE_TX2IE | CANINTE_TX1IE | - CANINTE_TX0IE | CANINTE_RX1IE | CANINTE_RX0IE | - CANINTF_MERRF); - - if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { - /* Put device into loopback mode */ - mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK); - } else { - /* Put device into normal mode */ - mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL); - - /* Wait for the device to enter normal mode */ - timeout = jiffies + HZ; - while (mcp251x_read_reg(spi, CANSTAT) & CANCTRL_REQOP_MASK) { - schedule(); - if (time_after(jiffies, timeout)) { - dev_err(&spi->dev, "MCP251x didn't" - " enter in normal mode\n"); - return; - } - } - } - priv->can.state = CAN_STATE_ERROR_ACTIVE; -} - -static int mcp251x_do_set_bittiming(struct net_device *net) -{ - struct mcp251x_priv *priv = netdev_priv(net); - struct can_bittiming *bt = &priv->can.bittiming; - struct spi_device *spi = priv->spi; - - mcp251x_write_reg(spi, CNF1, ((bt->sjw - 1) << CNF1_SJW_SHIFT) | - (bt->brp - 1)); - mcp251x_write_reg(spi, CNF2, CNF2_BTLMODE | - (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES ? - CNF2_SAM : 0) | - ((bt->phase_seg1 - 1) << CNF2_PS1_SHIFT) | - (bt->prop_seg - 1)); - mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK, - (bt->phase_seg2 - 1)); - dev_info(&spi->dev, "CNF: 0x%02x 0x%02x 0x%02x\n", - mcp251x_read_reg(spi, CNF1), - mcp251x_read_reg(spi, CNF2), - mcp251x_read_reg(spi, CNF3)); - - return 0; -} - -static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv, - struct spi_device *spi) -{ - int ret; - - ret = open_candev(net); - if (ret) { - dev_err(&spi->dev, "unable to set initial baudrate!\n"); - return ret; - } - - /* Enable RX0->RX1 buffer roll over and disable filters */ - mcp251x_write_bits(spi, RXBCTRL(0), - RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1, - RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1); - mcp251x_write_bits(spi, RXBCTRL(1), - RXBCTRL_RXM0 | RXBCTRL_RXM1, - RXBCTRL_RXM0 | RXBCTRL_RXM1); - return 0; -} - -static void mcp251x_hw_reset(struct spi_device *spi) -{ - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - int ret; - - mutex_lock(&priv->spi_lock); - - priv->spi_tx_buf[0] = INSTRUCTION_RESET; - - ret = spi_write(spi, priv->spi_tx_buf, 1); - - mutex_unlock(&priv->spi_lock); - - if (ret) - dev_err(&spi->dev, "reset failed: ret = %d\n", ret); - /* Wait for reset to finish */ - mdelay(10); -} - -static int mcp251x_hw_probe(struct spi_device *spi) -{ - int st1, st2; - - mcp251x_hw_reset(spi); - - /* - * Please note that these are "magic values" based on after - * reset defaults taken from data sheet which allows us to see - * if we really have a chip on the bus (we avoid common all - * zeroes or all ones situations) - */ - st1 = mcp251x_read_reg(spi, CANSTAT) & 0xEE; - st2 = mcp251x_read_reg(spi, CANCTRL) & 0x17; - - dev_dbg(&spi->dev, "CANSTAT 0x%02x CANCTRL 0x%02x\n", st1, st2); - - /* Check for power up default values */ - return (st1 == 0x80 && st2 == 0x07) ? 1 : 0; -} - -static irqreturn_t mcp251x_can_isr(int irq, void *dev_id) -{ - struct net_device *net = (struct net_device *)dev_id; - struct mcp251x_priv *priv = netdev_priv(net); - - /* Schedule bottom half */ - if (!work_pending(&priv->irq_work)) - queue_work(priv->wq, &priv->irq_work); - - return IRQ_HANDLED; -} - -static int mcp251x_open(struct net_device *net) -{ - struct mcp251x_priv *priv = netdev_priv(net); - struct spi_device *spi = priv->spi; - struct mcp251x_platform_data *pdata = spi->dev.platform_data; - int ret; - - if (pdata->transceiver_enable) - pdata->transceiver_enable(1); - - priv->force_quit = 0; - priv->tx_skb = NULL; - priv->tx_len = 0; - - ret = request_irq(spi->irq, mcp251x_can_isr, - IRQF_TRIGGER_FALLING, DEVICE_NAME, net); - if (ret) { - dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq); - if (pdata->transceiver_enable) - pdata->transceiver_enable(0); - return ret; - } - - mcp251x_hw_wakeup(spi); - mcp251x_hw_reset(spi); - ret = mcp251x_setup(net, priv, spi); - if (ret) { - free_irq(spi->irq, net); - if (pdata->transceiver_enable) - pdata->transceiver_enable(0); - return ret; - } - mcp251x_set_normal_mode(spi); - netif_wake_queue(net); - - return 0; -} - -static int mcp251x_stop(struct net_device *net) -{ - struct mcp251x_priv *priv = netdev_priv(net); - struct spi_device *spi = priv->spi; - struct mcp251x_platform_data *pdata = spi->dev.platform_data; - - close_candev(net); - - /* Disable and clear pending interrupts */ - mcp251x_write_reg(spi, CANINTE, 0x00); - mcp251x_write_reg(spi, CANINTF, 0x00); - - priv->force_quit = 1; - free_irq(spi->irq, net); - flush_workqueue(priv->wq); - - mcp251x_write_reg(spi, TXBCTRL(0), 0); - if (priv->tx_skb || priv->tx_len) - mcp251x_clean(net); - - mcp251x_hw_sleep(spi); - - if (pdata->transceiver_enable) - pdata->transceiver_enable(0); - - priv->can.state = CAN_STATE_STOPPED; - - return 0; -} - -static void mcp251x_tx_work_handler(struct work_struct *ws) -{ - struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv, - tx_work); - struct spi_device *spi = priv->spi; - struct net_device *net = priv->net; - struct can_frame *frame; - - if (priv->tx_skb) { - frame = (struct can_frame *)priv->tx_skb->data; - - if (priv->can.state == CAN_STATE_BUS_OFF) { - mcp251x_clean(net); - netif_wake_queue(net); - return; - } - if (frame->can_dlc > CAN_FRAME_MAX_DATA_LEN) - frame->can_dlc = CAN_FRAME_MAX_DATA_LEN; - mcp251x_hw_tx(spi, frame, 0); - priv->tx_len = 1 + frame->can_dlc; - can_put_echo_skb(priv->tx_skb, net, 0); - priv->tx_skb = NULL; - } -} - -static void mcp251x_irq_work_handler(struct work_struct *ws) -{ - struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv, - irq_work); - struct spi_device *spi = priv->spi; - struct net_device *net = priv->net; - u8 txbnctrl; - u8 intf; - enum can_state new_state; - - if (priv->after_suspend) { - mdelay(10); - mcp251x_hw_reset(spi); - mcp251x_setup(net, priv, spi); - if (priv->after_suspend & AFTER_SUSPEND_RESTART) { - mcp251x_set_normal_mode(spi); - } else if (priv->after_suspend & AFTER_SUSPEND_UP) { - netif_device_attach(net); - /* Clean since we lost tx buffer */ - if (priv->tx_skb || priv->tx_len) { - mcp251x_clean(net); - netif_wake_queue(net); - } - mcp251x_set_normal_mode(spi); - } else { - mcp251x_hw_sleep(spi); - } - priv->after_suspend = 0; - } - - if (priv->can.restart_ms == 0 && priv->can.state == CAN_STATE_BUS_OFF) - return; - - while (!priv->force_quit && !freezing(current)) { - u8 eflag = mcp251x_read_reg(spi, EFLG); - int can_id = 0, data1 = 0; - - mcp251x_write_reg(spi, EFLG, 0x00); - - if (priv->restart_tx) { - priv->restart_tx = 0; - mcp251x_write_reg(spi, TXBCTRL(0), 0); - if (priv->tx_skb || priv->tx_len) - mcp251x_clean(net); - netif_wake_queue(net); - can_id |= CAN_ERR_RESTARTED; - } - - if (priv->wake) { - /* Wait whilst the device wakes up */ - mdelay(10); - priv->wake = 0; - } - - intf = mcp251x_read_reg(spi, CANINTF); - mcp251x_write_bits(spi, CANINTF, intf, 0x00); - - /* Update can state */ - if (eflag & EFLG_TXBO) { - new_state = CAN_STATE_BUS_OFF; - can_id |= CAN_ERR_BUSOFF; - } else if (eflag & EFLG_TXEP) { - new_state = CAN_STATE_ERROR_PASSIVE; - can_id |= CAN_ERR_CRTL; - data1 |= CAN_ERR_CRTL_TX_PASSIVE; - } else if (eflag & EFLG_RXEP) { - new_state = CAN_STATE_ERROR_PASSIVE; - can_id |= CAN_ERR_CRTL; - data1 |= CAN_ERR_CRTL_RX_PASSIVE; - } else if (eflag & EFLG_TXWAR) { - new_state = CAN_STATE_ERROR_WARNING; - can_id |= CAN_ERR_CRTL; - data1 |= CAN_ERR_CRTL_TX_WARNING; - } else if (eflag & EFLG_RXWAR) { - new_state = CAN_STATE_ERROR_WARNING; - can_id |= CAN_ERR_CRTL; - data1 |= CAN_ERR_CRTL_RX_WARNING; - } else { - new_state = CAN_STATE_ERROR_ACTIVE; - } - - /* Update can state statistics */ - switch (priv->can.state) { - case CAN_STATE_ERROR_ACTIVE: - if (new_state >= CAN_STATE_ERROR_WARNING && - new_state <= CAN_STATE_BUS_OFF) - priv->can.can_stats.error_warning++; - case CAN_STATE_ERROR_WARNING: /* fallthrough */ - if (new_state >= CAN_STATE_ERROR_PASSIVE && - new_state <= CAN_STATE_BUS_OFF) - priv->can.can_stats.error_passive++; - break; - default: - break; - } - priv->can.state = new_state; - - if ((intf & CANINTF_ERRIF) || (can_id & CAN_ERR_RESTARTED)) { - struct sk_buff *skb; - struct can_frame *frame; - - /* Create error frame */ - skb = alloc_can_err_skb(net, &frame); - if (skb) { - /* Set error frame flags based on bus state */ - frame->can_id = can_id; - frame->data[1] = data1; - - /* Update net stats for overflows */ - if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) { - if (eflag & EFLG_RX0OVR) - net->stats.rx_over_errors++; - if (eflag & EFLG_RX1OVR) - net->stats.rx_over_errors++; - frame->can_id |= CAN_ERR_CRTL; - frame->data[1] |= - CAN_ERR_CRTL_RX_OVERFLOW; - } - - netif_rx(skb); - } else { - dev_info(&spi->dev, - "cannot allocate error skb\n"); - } - } - - if (priv->can.state == CAN_STATE_BUS_OFF) { - if (priv->can.restart_ms == 0) { - can_bus_off(net); - mcp251x_hw_sleep(spi); - return; - } - } - - if (intf == 0) - break; - - if (intf & CANINTF_WAKIF) - complete(&priv->awake); - - if (intf & CANINTF_MERRF) { - /* If there are pending Tx buffers, restart queue */ - txbnctrl = mcp251x_read_reg(spi, TXBCTRL(0)); - if (!(txbnctrl & TXBCTRL_TXREQ)) { - if (priv->tx_skb || priv->tx_len) - mcp251x_clean(net); - netif_wake_queue(net); - } - } - - if (intf & (CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF)) { - net->stats.tx_packets++; - net->stats.tx_bytes += priv->tx_len - 1; - if (priv->tx_len) { - can_get_echo_skb(net, 0); - priv->tx_len = 0; - } - netif_wake_queue(net); - } - - if (intf & CANINTF_RX0IF) - mcp251x_hw_rx(spi, 0); - - if (intf & CANINTF_RX1IF) - mcp251x_hw_rx(spi, 1); - } -} - -static const struct net_device_ops mcp251x_netdev_ops = { - .ndo_open = mcp251x_open, - .ndo_stop = mcp251x_stop, - .ndo_start_xmit = mcp251x_hard_start_xmit, -}; - -static int __devinit mcp251x_can_probe(struct spi_device *spi) -{ - struct net_device *net; - struct mcp251x_priv *priv; - struct mcp251x_platform_data *pdata = spi->dev.platform_data; - int ret = -ENODEV; - - if (!pdata) - /* Platform data is required for osc freq */ - goto error_out; - - /* Allocate can/net device */ - net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX); - if (!net) { - ret = -ENOMEM; - goto error_alloc; - } - - net->netdev_ops = &mcp251x_netdev_ops; - net->flags |= IFF_ECHO; - - priv = netdev_priv(net); - priv->can.bittiming_const = &mcp251x_bittiming_const; - priv->can.do_set_mode = mcp251x_do_set_mode; - priv->can.clock.freq = pdata->oscillator_frequency / 2; - priv->can.do_set_bittiming = mcp251x_do_set_bittiming; - priv->net = net; - dev_set_drvdata(&spi->dev, priv); - - priv->spi = spi; - mutex_init(&priv->spi_lock); - - /* If requested, allocate DMA buffers */ - if (mcp251x_enable_dma) { - spi->dev.coherent_dma_mask = ~0; - - /* - * Minimum coherent DMA allocation is PAGE_SIZE, so allocate - * that much and share it between Tx and Rx DMA buffers. - */ - priv->spi_tx_buf = dma_alloc_coherent(&spi->dev, - PAGE_SIZE, - &priv->spi_tx_dma, - GFP_DMA); - - if (priv->spi_tx_buf) { - priv->spi_rx_buf = (u8 *)(priv->spi_tx_buf + - (PAGE_SIZE / 2)); - priv->spi_rx_dma = (dma_addr_t)(priv->spi_tx_dma + - (PAGE_SIZE / 2)); - } else { - /* Fall back to non-DMA */ - mcp251x_enable_dma = 0; - } - } - - /* Allocate non-DMA buffers */ - if (!mcp251x_enable_dma) { - priv->spi_tx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL); - if (!priv->spi_tx_buf) { - ret = -ENOMEM; - goto error_tx_buf; - } - priv->spi_rx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL); - if (!priv->spi_tx_buf) { - ret = -ENOMEM; - goto error_rx_buf; - } - } - - if (pdata->power_enable) - pdata->power_enable(1); - - /* Call out to platform specific setup */ - if (pdata->board_specific_setup) - pdata->board_specific_setup(spi); - - SET_NETDEV_DEV(net, &spi->dev); - - priv->wq = create_freezeable_workqueue("mcp251x_wq"); - - INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler); - INIT_WORK(&priv->irq_work, mcp251x_irq_work_handler); - - init_completion(&priv->awake); - - /* Configure the SPI bus */ - spi->mode = SPI_MODE_0; - spi->bits_per_word = 8; - spi_setup(spi); - - if (!mcp251x_hw_probe(spi)) { - dev_info(&spi->dev, "Probe failed\n"); - goto error_probe; - } - mcp251x_hw_sleep(spi); - - if (pdata->transceiver_enable) - pdata->transceiver_enable(0); - - ret = register_candev(net); - if (!ret) { - dev_info(&spi->dev, "probed\n"); - return ret; - } -error_probe: - if (!mcp251x_enable_dma) - kfree(priv->spi_rx_buf); -error_rx_buf: - if (!mcp251x_enable_dma) - kfree(priv->spi_tx_buf); -error_tx_buf: - free_candev(net); - if (mcp251x_enable_dma) - dma_free_coherent(&spi->dev, PAGE_SIZE, - priv->spi_tx_buf, priv->spi_tx_dma); -error_alloc: - if (pdata->power_enable) - pdata->power_enable(0); - dev_err(&spi->dev, "probe failed\n"); -error_out: - return ret; -} - -static int __devexit mcp251x_can_remove(struct spi_device *spi) -{ - struct mcp251x_platform_data *pdata = spi->dev.platform_data; - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - struct net_device *net = priv->net; - - unregister_candev(net); - free_candev(net); - - priv->force_quit = 1; - flush_workqueue(priv->wq); - destroy_workqueue(priv->wq); - - if (mcp251x_enable_dma) { - dma_free_coherent(&spi->dev, PAGE_SIZE, - priv->spi_tx_buf, priv->spi_tx_dma); - } else { - kfree(priv->spi_tx_buf); - kfree(priv->spi_rx_buf); - } - - if (pdata->power_enable) - pdata->power_enable(0); - - return 0; -} - -#ifdef CONFIG_PM -static int mcp251x_can_suspend(struct spi_device *spi, pm_message_t state) -{ - struct mcp251x_platform_data *pdata = spi->dev.platform_data; - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - struct net_device *net = priv->net; - - if (netif_running(net)) { - netif_device_detach(net); - - mcp251x_hw_sleep(spi); - if (pdata->transceiver_enable) - pdata->transceiver_enable(0); - priv->after_suspend = AFTER_SUSPEND_UP; - } else { - priv->after_suspend = AFTER_SUSPEND_DOWN; - } - - if (pdata->power_enable) { - pdata->power_enable(0); - priv->after_suspend |= AFTER_SUSPEND_POWER; - } - - return 0; -} - -static int mcp251x_can_resume(struct spi_device *spi) -{ - struct mcp251x_platform_data *pdata = spi->dev.platform_data; - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - - if (priv->after_suspend & AFTER_SUSPEND_POWER) { - pdata->power_enable(1); - queue_work(priv->wq, &priv->irq_work); - } else { - if (priv->after_suspend & AFTER_SUSPEND_UP) { - if (pdata->transceiver_enable) - pdata->transceiver_enable(1); - queue_work(priv->wq, &priv->irq_work); - } else { - priv->after_suspend = 0; - } - } - return 0; -} -#else -#define mcp251x_can_suspend NULL -#define mcp251x_can_resume NULL -#endif - -static struct spi_driver mcp251x_can_driver = { - .driver = { - .name = DEVICE_NAME, - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = mcp251x_can_probe, - .remove = __devexit_p(mcp251x_can_remove), - .suspend = mcp251x_can_suspend, - .resume = mcp251x_can_resume, -}; - -static int __init mcp251x_can_init(void) -{ - return spi_register_driver(&mcp251x_can_driver); -} - -static void __exit mcp251x_can_exit(void) -{ - spi_unregister_driver(&mcp251x_can_driver); -} - -module_init(mcp251x_can_init); -module_exit(mcp251x_can_exit); - -MODULE_AUTHOR("Chris Elston , " - "Christian Pellegrin "); -MODULE_DESCRIPTION("Microchip 251x CAN driver"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/net/can/mscan/Makefile b/trunk/drivers/net/can/mscan/Makefile deleted file mode 100644 index 2bd9f04c7908..000000000000 --- a/trunk/drivers/net/can/mscan/Makefile +++ /dev/null @@ -1,5 +0,0 @@ - -obj-$(CONFIG_CAN_MPC52XX) += mscan-mpc52xx.o -mscan-mpc52xx-objs := mscan.o mpc52xx_can.o - -ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/trunk/drivers/net/can/mscan/mpc52xx_can.c b/trunk/drivers/net/can/mscan/mpc52xx_can.c deleted file mode 100644 index 4707a82f1ae0..000000000000 --- a/trunk/drivers/net/can/mscan/mpc52xx_can.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * CAN bus driver for the Freescale MPC5xxx embedded CPU. - * - * Copyright (C) 2004-2005 Andrey Volkov , - * Varma Electronics Oy - * Copyright (C) 2008-2009 Wolfgang Grandegger - * Copyright (C) 2009 Wolfram Sang, Pengutronix - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the version 2 of the GNU General Public License - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mscan.h" - - -#define DRV_NAME "mpc5xxx_can" - -static struct of_device_id mpc52xx_cdm_ids[] __devinitdata = { - { .compatible = "fsl,mpc5200-cdm", }, - { .compatible = "fsl,mpc5200b-cdm", }, - {} -}; - -/* - * Get the frequency of the external oscillator clock connected - * to the SYS_XTAL_IN pin, or return 0 if it cannot be determined. - */ -static unsigned int __devinit mpc52xx_can_xtal_freq(struct of_device *of) -{ - struct mpc52xx_cdm __iomem *cdm; - struct device_node *np_cdm; - unsigned int freq; - u32 val; - - freq = mpc5xxx_get_bus_frequency(of->node); - if (!freq) - return 0; - - /* - * Determine SYS_XTAL_IN frequency from the clock domain settings - */ - np_cdm = of_find_matching_node(NULL, mpc52xx_cdm_ids); - if (!np_cdm) { - dev_err(&of->dev, "can't get clock node!\n"); - return 0; - } - cdm = of_iomap(np_cdm, 0); - of_node_put(np_cdm); - - if (in_8(&cdm->ipb_clk_sel) & 0x1) - freq *= 2; - val = in_be32(&cdm->rstcfg); - if (val & (1 << 5)) - freq *= 8; - else - freq *= 4; - if (val & (1 << 6)) - freq /= 12; - else - freq /= 16; - - iounmap(cdm); - - return freq; -} - -/* - * Get frequency of the MSCAN clock source - * - * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock (IP_CLK) - * can be selected. According to the MPC5200 user's manual, the oscillator - * clock is the better choice as it has less jitter but due to a hardware - * bug, it can not be selected for the old MPC5200 Rev. A chips. - */ - -static unsigned int __devinit mpc52xx_can_clock_freq(struct of_device *of, - int clock_src) -{ - unsigned int pvr; - - pvr = mfspr(SPRN_PVR); - - if (clock_src == MSCAN_CLKSRC_BUS || pvr == 0x80822011) - return mpc5xxx_get_bus_frequency(of->node); - - return mpc52xx_can_xtal_freq(of); -} - -static int __devinit mpc5xxx_can_probe(struct of_device *ofdev, - const struct of_device_id *id) -{ - struct device_node *np = ofdev->node; - struct net_device *dev; - struct mscan_priv *priv; - void __iomem *base; - const char *clk_src; - int err, irq, clock_src; - - base = of_iomap(ofdev->node, 0); - if (!base) { - dev_err(&ofdev->dev, "couldn't ioremap\n"); - err = -ENOMEM; - goto exit_release_mem; - } - - irq = irq_of_parse_and_map(np, 0); - if (!irq) { - dev_err(&ofdev->dev, "no irq found\n"); - err = -ENODEV; - goto exit_unmap_mem; - } - - dev = alloc_mscandev(); - if (!dev) { - err = -ENOMEM; - goto exit_dispose_irq; - } - - priv = netdev_priv(dev); - priv->reg_base = base; - dev->irq = irq; - - /* - * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock - * (IP_CLK) can be selected as MSCAN clock source. According to - * the MPC5200 user's manual, the oscillator clock is the better - * choice as it has less jitter. For this reason, it is selected - * by default. - */ - clk_src = of_get_property(np, "fsl,mscan-clk-src", NULL); - if (clk_src && strcmp(clk_src, "ip") == 0) - clock_src = MSCAN_CLKSRC_BUS; - else - clock_src = MSCAN_CLKSRC_XTAL; - priv->can.clock.freq = mpc52xx_can_clock_freq(ofdev, clock_src); - if (!priv->can.clock.freq) { - dev_err(&ofdev->dev, "couldn't get MSCAN clock frequency\n"); - err = -ENODEV; - goto exit_free_mscan; - } - - SET_NETDEV_DEV(dev, &ofdev->dev); - - err = register_mscandev(dev, clock_src); - if (err) { - dev_err(&ofdev->dev, "registering %s failed (err=%d)\n", - DRV_NAME, err); - goto exit_free_mscan; - } - - dev_set_drvdata(&ofdev->dev, dev); - - dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n", - priv->reg_base, dev->irq, priv->can.clock.freq); - - return 0; - -exit_free_mscan: - free_candev(dev); -exit_dispose_irq: - irq_dispose_mapping(irq); -exit_unmap_mem: - iounmap(base); -exit_release_mem: - return err; -} - -static int __devexit mpc5xxx_can_remove(struct of_device *ofdev) -{ - struct net_device *dev = dev_get_drvdata(&ofdev->dev); - struct mscan_priv *priv = netdev_priv(dev); - - dev_set_drvdata(&ofdev->dev, NULL); - - unregister_mscandev(dev); - iounmap(priv->reg_base); - irq_dispose_mapping(dev->irq); - free_candev(dev); - - return 0; -} - -#ifdef CONFIG_PM -static struct mscan_regs saved_regs; -static int mpc5xxx_can_suspend(struct of_device *ofdev, pm_message_t state) -{ - struct net_device *dev = dev_get_drvdata(&ofdev->dev); - struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - - _memcpy_fromio(&saved_regs, regs, sizeof(*regs)); - - return 0; -} - -static int mpc5xxx_can_resume(struct of_device *ofdev) -{ - struct net_device *dev = dev_get_drvdata(&ofdev->dev); - struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - - regs->canctl0 |= MSCAN_INITRQ; - while ((regs->canctl1 & MSCAN_INITAK) == 0) - udelay(10); - - regs->canctl1 = saved_regs.canctl1; - regs->canbtr0 = saved_regs.canbtr0; - regs->canbtr1 = saved_regs.canbtr1; - regs->canidac = saved_regs.canidac; - - /* restore masks, buffers etc. */ - _memcpy_toio(®s->canidar1_0, (void *)&saved_regs.canidar1_0, - sizeof(*regs) - offsetof(struct mscan_regs, canidar1_0)); - - regs->canctl0 &= ~MSCAN_INITRQ; - regs->cantbsel = saved_regs.cantbsel; - regs->canrier = saved_regs.canrier; - regs->cantier = saved_regs.cantier; - regs->canctl0 = saved_regs.canctl0; - - return 0; -} -#endif - -static struct of_device_id __devinitdata mpc5xxx_can_table[] = { - {.compatible = "fsl,mpc5200-mscan"}, - {.compatible = "fsl,mpc5200b-mscan"}, - {}, -}; - -static struct of_platform_driver mpc5xxx_can_driver = { - .owner = THIS_MODULE, - .name = "mpc5xxx_can", - .probe = mpc5xxx_can_probe, - .remove = __devexit_p(mpc5xxx_can_remove), -#ifdef CONFIG_PM - .suspend = mpc5xxx_can_suspend, - .resume = mpc5xxx_can_resume, -#endif - .match_table = mpc5xxx_can_table, -}; - -static int __init mpc5xxx_can_init(void) -{ - return of_register_platform_driver(&mpc5xxx_can_driver); -} -module_init(mpc5xxx_can_init); - -static void __exit mpc5xxx_can_exit(void) -{ - return of_unregister_platform_driver(&mpc5xxx_can_driver); -}; -module_exit(mpc5xxx_can_exit); - -MODULE_AUTHOR("Wolfgang Grandegger "); -MODULE_DESCRIPTION("Freescale MPC5200 CAN driver"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/net/can/mscan/mscan.c b/trunk/drivers/net/can/mscan/mscan.c deleted file mode 100644 index 49542cab9df4..000000000000 --- a/trunk/drivers/net/can/mscan/mscan.c +++ /dev/null @@ -1,699 +0,0 @@ -/* - * CAN bus driver for the alone generic (as possible as) MSCAN controller. - * - * Copyright (C) 2005-2006 Andrey Volkov , - * Varma Electronics Oy - * Copyright (C) 2008-2009 Wolfgang Grandegger - * Copytight (C) 2008-2009 Pengutronix - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the version 2 of the GNU General Public License - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mscan.h" - -#define MSCAN_NORMAL_MODE 0 -#define MSCAN_SLEEP_MODE MSCAN_SLPRQ -#define MSCAN_INIT_MODE (MSCAN_INITRQ | MSCAN_SLPRQ) -#define MSCAN_POWEROFF_MODE (MSCAN_CSWAI | MSCAN_SLPRQ) -#define MSCAN_SET_MODE_RETRIES 255 -#define MSCAN_ECHO_SKB_MAX 3 - -#define BTR0_BRP_MASK 0x3f -#define BTR0_SJW_SHIFT 6 -#define BTR0_SJW_MASK (0x3 << BTR0_SJW_SHIFT) - -#define BTR1_TSEG1_MASK 0xf -#define BTR1_TSEG2_SHIFT 4 -#define BTR1_TSEG2_MASK (0x7 << BTR1_TSEG2_SHIFT) -#define BTR1_SAM_SHIFT 7 - -#define BTR0_SET_BRP(brp) (((brp) - 1) & BTR0_BRP_MASK) -#define BTR0_SET_SJW(sjw) ((((sjw) - 1) << BTR0_SJW_SHIFT) & \ - BTR0_SJW_MASK) - -#define BTR1_SET_TSEG1(tseg1) (((tseg1) - 1) & BTR1_TSEG1_MASK) -#define BTR1_SET_TSEG2(tseg2) ((((tseg2) - 1) << BTR1_TSEG2_SHIFT) & \ - BTR1_TSEG2_MASK) -#define BTR1_SET_SAM(sam) ((sam) ? 1 << BTR1_SAM_SHIFT : 0) - -static struct can_bittiming_const mscan_bittiming_const = { - .name = "mscan", - .tseg1_min = 4, - .tseg1_max = 16, - .tseg2_min = 2, - .tseg2_max = 8, - .sjw_max = 4, - .brp_min = 1, - .brp_max = 64, - .brp_inc = 1, -}; - -struct mscan_state { - u8 mode; - u8 canrier; - u8 cantier; -}; - -#define F_RX_PROGRESS 0 -#define F_TX_PROGRESS 1 -#define F_TX_WAIT_ALL 2 - -static enum can_state state_map[] = { - CAN_STATE_ERROR_ACTIVE, - CAN_STATE_ERROR_WARNING, - CAN_STATE_ERROR_PASSIVE, - CAN_STATE_BUS_OFF -}; - -static int mscan_set_mode(struct net_device *dev, u8 mode) -{ - struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - int ret = 0; - int i; - u8 canctl1; - - if (mode != MSCAN_NORMAL_MODE) { - - if (priv->tx_active) { - /* Abort transfers before going to sleep */# - out_8(®s->cantarq, priv->tx_active); - /* Suppress TX done interrupts */ - out_8(®s->cantier, 0); - } - - canctl1 = in_8(®s->canctl1); - if ((mode & MSCAN_SLPRQ) && (canctl1 & MSCAN_SLPAK) == 0) { - out_8(®s->canctl0, - in_8(®s->canctl0) | MSCAN_SLPRQ); - for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) { - if (in_8(®s->canctl1) & MSCAN_SLPAK) - break; - udelay(100); - } - /* - * The mscan controller will fail to enter sleep mode, - * while there are irregular activities on bus, like - * somebody keeps retransmitting. This behavior is - * undocumented and seems to differ between mscan built - * in mpc5200b and mpc5200. We proceed in that case, - * since otherwise the slprq will be kept set and the - * controller will get stuck. NOTE: INITRQ or CSWAI - * will abort all active transmit actions, if still - * any, at once. - */ - if (i >= MSCAN_SET_MODE_RETRIES) - dev_dbg(dev->dev.parent, - "device failed to enter sleep mode. " - "We proceed anyhow.\n"); - else - priv->can.state = CAN_STATE_SLEEPING; - } - - if ((mode & MSCAN_INITRQ) && (canctl1 & MSCAN_INITAK) == 0) { - out_8(®s->canctl0, - in_8(®s->canctl0) | MSCAN_INITRQ); - for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) { - if (in_8(®s->canctl1) & MSCAN_INITAK) - break; - } - if (i >= MSCAN_SET_MODE_RETRIES) - ret = -ENODEV; - } - if (!ret) - priv->can.state = CAN_STATE_STOPPED; - - if (mode & MSCAN_CSWAI) - out_8(®s->canctl0, - in_8(®s->canctl0) | MSCAN_CSWAI); - - } else { - canctl1 = in_8(®s->canctl1); - if (canctl1 & (MSCAN_SLPAK | MSCAN_INITAK)) { - out_8(®s->canctl0, in_8(®s->canctl0) & - ~(MSCAN_SLPRQ | MSCAN_INITRQ)); - for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) { - canctl1 = in_8(®s->canctl1); - if (!(canctl1 & (MSCAN_INITAK | MSCAN_SLPAK))) - break; - } - if (i >= MSCAN_SET_MODE_RETRIES) - ret = -ENODEV; - else - priv->can.state = CAN_STATE_ERROR_ACTIVE; - } - } - return ret; -} - -static int mscan_start(struct net_device *dev) -{ - struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - u8 canrflg; - int err; - - out_8(®s->canrier, 0); - - INIT_LIST_HEAD(&priv->tx_head); - priv->prev_buf_id = 0; - priv->cur_pri = 0; - priv->tx_active = 0; - priv->shadow_canrier = 0; - priv->flags = 0; - - err = mscan_set_mode(dev, MSCAN_NORMAL_MODE); - if (err) - return err; - - canrflg = in_8(®s->canrflg); - priv->shadow_statflg = canrflg & MSCAN_STAT_MSK; - priv->can.state = state_map[max(MSCAN_STATE_RX(canrflg), - MSCAN_STATE_TX(canrflg))]; - out_8(®s->cantier, 0); - - /* Enable receive interrupts. */ - out_8(®s->canrier, MSCAN_OVRIE | MSCAN_RXFIE | MSCAN_CSCIE | - MSCAN_RSTATE1 | MSCAN_RSTATE0 | MSCAN_TSTATE1 | MSCAN_TSTATE0); - - return 0; -} - -static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct can_frame *frame = (struct can_frame *)skb->data; - struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - int i, rtr, buf_id; - u32 can_id; - - if (frame->can_dlc > 8) - return -EINVAL; - - out_8(®s->cantier, 0); - - i = ~priv->tx_active & MSCAN_TXE; - buf_id = ffs(i) - 1; - switch (hweight8(i)) { - case 0: - netif_stop_queue(dev); - dev_err(dev->dev.parent, "Tx Ring full when queue awake!\n"); - return NETDEV_TX_BUSY; - case 1: - /* - * if buf_id < 3, then current frame will be send out of order, - * since buffer with lower id have higher priority (hell..) - */ - netif_stop_queue(dev); - case 2: - if (buf_id < priv->prev_buf_id) { - priv->cur_pri++; - if (priv->cur_pri == 0xff) { - set_bit(F_TX_WAIT_ALL, &priv->flags); - netif_stop_queue(dev); - } - } - set_bit(F_TX_PROGRESS, &priv->flags); - break; - } - priv->prev_buf_id = buf_id; - out_8(®s->cantbsel, i); - - rtr = frame->can_id & CAN_RTR_FLAG; - - if (frame->can_id & CAN_EFF_FLAG) { - can_id = (frame->can_id & CAN_EFF_MASK) << 1; - if (rtr) - can_id |= 1; - out_be16(®s->tx.idr3_2, can_id); - - can_id >>= 16; - can_id = (can_id & 0x7) | ((can_id << 2) & 0xffe0) | (3 << 3); - } else { - can_id = (frame->can_id & CAN_SFF_MASK) << 5; - if (rtr) - can_id |= 1 << 4; - } - out_be16(®s->tx.idr1_0, can_id); - - if (!rtr) { - void __iomem *data = ®s->tx.dsr1_0; - u16 *payload = (u16 *) frame->data; - /* It is safe to write into dsr[dlc+1] */ - for (i = 0; i < (frame->can_dlc + 1) / 2; i++) { - out_be16(data, *payload++); - data += 2 + _MSCAN_RESERVED_DSR_SIZE; - } - } - - out_8(®s->tx.dlr, frame->can_dlc); - out_8(®s->tx.tbpr, priv->cur_pri); - - /* Start transmission. */ - out_8(®s->cantflg, 1 << buf_id); - - if (!test_bit(F_TX_PROGRESS, &priv->flags)) - dev->trans_start = jiffies; - - list_add_tail(&priv->tx_queue[buf_id].list, &priv->tx_head); - - can_put_echo_skb(skb, dev, buf_id); - - /* Enable interrupt. */ - priv->tx_active |= 1 << buf_id; - out_8(®s->cantier, priv->tx_active); - - return NETDEV_TX_OK; -} - -/* This function returns the old state to see where we came from */ -static enum can_state check_set_state(struct net_device *dev, u8 canrflg) -{ - struct mscan_priv *priv = netdev_priv(dev); - enum can_state state, old_state = priv->can.state; - - if (canrflg & MSCAN_CSCIF && old_state <= CAN_STATE_BUS_OFF) { - state = state_map[max(MSCAN_STATE_RX(canrflg), - MSCAN_STATE_TX(canrflg))]; - priv->can.state = state; - } - return old_state; -} - -static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame) -{ - struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - u32 can_id; - int i; - - can_id = in_be16(®s->rx.idr1_0); - if (can_id & (1 << 3)) { - frame->can_id = CAN_EFF_FLAG; - can_id = ((can_id << 16) | in_be16(®s->rx.idr3_2)); - can_id = ((can_id & 0xffe00000) | - ((can_id & 0x7ffff) << 2)) >> 2; - } else { - can_id >>= 4; - frame->can_id = 0; - } - - frame->can_id |= can_id >> 1; - if (can_id & 1) - frame->can_id |= CAN_RTR_FLAG; - frame->can_dlc = in_8(®s->rx.dlr) & 0xf; - - if (!(frame->can_id & CAN_RTR_FLAG)) { - void __iomem *data = ®s->rx.dsr1_0; - u16 *payload = (u16 *) frame->data; - for (i = 0; i < (frame->can_dlc + 1) / 2; i++) { - *payload++ = in_be16(data); - data += 2 + _MSCAN_RESERVED_DSR_SIZE; - } - } - - out_8(®s->canrflg, MSCAN_RXF); -} - -static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame, - u8 canrflg) -{ - struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - struct net_device_stats *stats = &dev->stats; - enum can_state old_state; - - dev_dbg(dev->dev.parent, "error interrupt (canrflg=%#x)\n", canrflg); - frame->can_id = CAN_ERR_FLAG; - - if (canrflg & MSCAN_OVRIF) { - frame->can_id |= CAN_ERR_CRTL; - frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; - stats->rx_over_errors++; - stats->rx_errors++; - } else - frame->data[1] = 0; - - old_state = check_set_state(dev, canrflg); - /* State changed */ - if (old_state != priv->can.state) { - switch (priv->can.state) { - case CAN_STATE_ERROR_WARNING: - frame->can_id |= CAN_ERR_CRTL; - priv->can.can_stats.error_warning++; - if ((priv->shadow_statflg & MSCAN_RSTAT_MSK) < - (canrflg & MSCAN_RSTAT_MSK)) - frame->data[1] |= CAN_ERR_CRTL_RX_WARNING; - - if ((priv->shadow_statflg & MSCAN_TSTAT_MSK) < - (canrflg & MSCAN_TSTAT_MSK)) - frame->data[1] |= CAN_ERR_CRTL_TX_WARNING; - break; - case CAN_STATE_ERROR_PASSIVE: - frame->can_id |= CAN_ERR_CRTL; - priv->can.can_stats.error_passive++; - frame->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; - break; - case CAN_STATE_BUS_OFF: - frame->can_id |= CAN_ERR_BUSOFF; - /* - * The MSCAN on the MPC5200 does recover from bus-off - * automatically. To avoid that we stop the chip doing - * a light-weight stop (we are in irq-context). - */ - out_8(®s->cantier, 0); - out_8(®s->canrier, 0); - out_8(®s->canctl0, in_8(®s->canctl0) | - MSCAN_SLPRQ | MSCAN_INITRQ); - can_bus_off(dev); - break; - default: - break; - } - } - priv->shadow_statflg = canrflg & MSCAN_STAT_MSK; - frame->can_dlc = CAN_ERR_DLC; - out_8(®s->canrflg, MSCAN_ERR_IF); -} - -static int mscan_rx_poll(struct napi_struct *napi, int quota) -{ - struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi); - struct net_device *dev = napi->dev; - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - struct net_device_stats *stats = &dev->stats; - int npackets = 0; - int ret = 1; - struct sk_buff *skb; - struct can_frame *frame; - u8 canrflg; - - while (npackets < quota && ((canrflg = in_8(®s->canrflg)) & - (MSCAN_RXF | MSCAN_ERR_IF))) { - - skb = alloc_can_skb(dev, &frame); - if (!skb) { - if (printk_ratelimit()) - dev_notice(dev->dev.parent, "packet dropped\n"); - stats->rx_dropped++; - out_8(®s->canrflg, canrflg); - continue; - } - - if (canrflg & MSCAN_RXF) - mscan_get_rx_frame(dev, frame); - else if (canrflg & MSCAN_ERR_IF) - mscan_get_err_frame(dev, frame, canrflg); - - stats->rx_packets++; - stats->rx_bytes += frame->can_dlc; - npackets++; - netif_receive_skb(skb); - } - - if (!(in_8(®s->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) { - napi_complete(&priv->napi); - clear_bit(F_RX_PROGRESS, &priv->flags); - if (priv->can.state < CAN_STATE_BUS_OFF) - out_8(®s->canrier, priv->shadow_canrier); - ret = 0; - } - return ret; -} - -static irqreturn_t mscan_isr(int irq, void *dev_id) -{ - struct net_device *dev = (struct net_device *)dev_id; - struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - struct net_device_stats *stats = &dev->stats; - u8 cantier, cantflg, canrflg; - irqreturn_t ret = IRQ_NONE; - - cantier = in_8(®s->cantier) & MSCAN_TXE; - cantflg = in_8(®s->cantflg) & cantier; - - if (cantier && cantflg) { - - struct list_head *tmp, *pos; - - list_for_each_safe(pos, tmp, &priv->tx_head) { - struct tx_queue_entry *entry = - list_entry(pos, struct tx_queue_entry, list); - u8 mask = entry->mask; - - if (!(cantflg & mask)) - continue; - - out_8(®s->cantbsel, mask); - stats->tx_bytes += in_8(®s->tx.dlr); - stats->tx_packets++; - can_get_echo_skb(dev, entry->id); - priv->tx_active &= ~mask; - list_del(pos); - } - - if (list_empty(&priv->tx_head)) { - clear_bit(F_TX_WAIT_ALL, &priv->flags); - clear_bit(F_TX_PROGRESS, &priv->flags); - priv->cur_pri = 0; - } else - dev->trans_start = jiffies; - - if (!test_bit(F_TX_WAIT_ALL, &priv->flags)) - netif_wake_queue(dev); - - out_8(®s->cantier, priv->tx_active); - ret = IRQ_HANDLED; - } - - canrflg = in_8(®s->canrflg); - if ((canrflg & ~MSCAN_STAT_MSK) && - !test_and_set_bit(F_RX_PROGRESS, &priv->flags)) { - if (canrflg & ~MSCAN_STAT_MSK) { - priv->shadow_canrier = in_8(®s->canrier); - out_8(®s->canrier, 0); - napi_schedule(&priv->napi); - ret = IRQ_HANDLED; - } else - clear_bit(F_RX_PROGRESS, &priv->flags); - } - return ret; -} - -static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode) -{ - - struct mscan_priv *priv = netdev_priv(dev); - int ret = 0; - - if (!priv->open_time) - return -EINVAL; - - switch (mode) { - case CAN_MODE_SLEEP: - case CAN_MODE_STOP: - netif_stop_queue(dev); - mscan_set_mode(dev, - (mode == - CAN_MODE_STOP) ? MSCAN_INIT_MODE : - MSCAN_SLEEP_MODE); - break; - case CAN_MODE_START: - if (priv->can.state <= CAN_STATE_BUS_OFF) - mscan_set_mode(dev, MSCAN_INIT_MODE); - ret = mscan_start(dev); - if (ret) - break; - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - return ret; -} - -static int mscan_do_set_bittiming(struct net_device *dev) -{ - struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - struct can_bittiming *bt = &priv->can.bittiming; - u8 btr0, btr1; - - btr0 = BTR0_SET_BRP(bt->brp) | BTR0_SET_SJW(bt->sjw); - btr1 = (BTR1_SET_TSEG1(bt->prop_seg + bt->phase_seg1) | - BTR1_SET_TSEG2(bt->phase_seg2) | - BTR1_SET_SAM(priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)); - - dev_info(dev->dev.parent, "setting BTR0=0x%02x BTR1=0x%02x\n", - btr0, btr1); - - out_8(®s->canbtr0, btr0); - out_8(®s->canbtr1, btr1); - - return 0; -} - -static int mscan_open(struct net_device *dev) -{ - int ret; - struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - - /* common open */ - ret = open_candev(dev); - if (ret) - return ret; - - napi_enable(&priv->napi); - - ret = request_irq(dev->irq, mscan_isr, 0, dev->name, dev); - if (ret < 0) { - napi_disable(&priv->napi); - printk(KERN_ERR "%s - failed to attach interrupt\n", - dev->name); - return ret; - } - - priv->open_time = jiffies; - - out_8(®s->canctl1, in_8(®s->canctl1) & ~MSCAN_LISTEN); - - ret = mscan_start(dev); - if (ret) - return ret; - - netif_start_queue(dev); - - return 0; -} - -static int mscan_close(struct net_device *dev) -{ - struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - - netif_stop_queue(dev); - napi_disable(&priv->napi); - - out_8(®s->cantier, 0); - out_8(®s->canrier, 0); - mscan_set_mode(dev, MSCAN_INIT_MODE); - close_candev(dev); - free_irq(dev->irq, dev); - priv->open_time = 0; - - return 0; -} - -static const struct net_device_ops mscan_netdev_ops = { - .ndo_open = mscan_open, - .ndo_stop = mscan_close, - .ndo_start_xmit = mscan_start_xmit, -}; - -int register_mscandev(struct net_device *dev, int clock_src) -{ - struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - u8 ctl1; - - ctl1 = in_8(®s->canctl1); - if (clock_src) - ctl1 |= MSCAN_CLKSRC; - else - ctl1 &= ~MSCAN_CLKSRC; - - ctl1 |= MSCAN_CANE; - out_8(®s->canctl1, ctl1); - udelay(100); - - /* acceptance mask/acceptance code (accept everything) */ - out_be16(®s->canidar1_0, 0); - out_be16(®s->canidar3_2, 0); - out_be16(®s->canidar5_4, 0); - out_be16(®s->canidar7_6, 0); - - out_be16(®s->canidmr1_0, 0xffff); - out_be16(®s->canidmr3_2, 0xffff); - out_be16(®s->canidmr5_4, 0xffff); - out_be16(®s->canidmr7_6, 0xffff); - /* Two 32 bit Acceptance Filters */ - out_8(®s->canidac, MSCAN_AF_32BIT); - - mscan_set_mode(dev, MSCAN_INIT_MODE); - - return register_candev(dev); -} -EXPORT_SYMBOL_GPL(register_mscandev); - -void unregister_mscandev(struct net_device *dev) -{ - struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; - mscan_set_mode(dev, MSCAN_INIT_MODE); - out_8(®s->canctl1, in_8(®s->canctl1) & ~MSCAN_CANE); - unregister_candev(dev); -} -EXPORT_SYMBOL_GPL(unregister_mscandev); - -struct net_device *alloc_mscandev(void) -{ - struct net_device *dev; - struct mscan_priv *priv; - int i; - - dev = alloc_candev(sizeof(struct mscan_priv), MSCAN_ECHO_SKB_MAX); - if (!dev) - return NULL; - priv = netdev_priv(dev); - - dev->netdev_ops = &mscan_netdev_ops; - - dev->flags |= IFF_ECHO; /* we support local echo */ - - netif_napi_add(dev, &priv->napi, mscan_rx_poll, 8); - - priv->can.bittiming_const = &mscan_bittiming_const; - priv->can.do_set_bittiming = mscan_do_set_bittiming; - priv->can.do_set_mode = mscan_do_set_mode; - - for (i = 0; i < TX_QUEUE_SIZE; i++) { - priv->tx_queue[i].id = i; - priv->tx_queue[i].mask = 1 << i; - } - - return dev; -} -EXPORT_SYMBOL_GPL(alloc_mscandev); - -MODULE_AUTHOR("Andrey Volkov "); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("CAN port driver for a MSCAN based chips"); diff --git a/trunk/drivers/net/can/mscan/mscan.h b/trunk/drivers/net/can/mscan/mscan.h deleted file mode 100644 index 57820f5fb817..000000000000 --- a/trunk/drivers/net/can/mscan/mscan.h +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Definitions of consts/structs to drive the Freescale MSCAN. - * - * Copyright (C) 2005-2006 Andrey Volkov , - * Varma Electronics Oy - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the version 2 of the GNU General Public License - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __MSCAN_H__ -#define __MSCAN_H__ - -#include - -/* MSCAN control register 0 (CANCTL0) bits */ -#define MSCAN_RXFRM 0x80 -#define MSCAN_RXACT 0x40 -#define MSCAN_CSWAI 0x20 -#define MSCAN_SYNCH 0x10 -#define MSCAN_TIME 0x08 -#define MSCAN_WUPE 0x04 -#define MSCAN_SLPRQ 0x02 -#define MSCAN_INITRQ 0x01 - -/* MSCAN control register 1 (CANCTL1) bits */ -#define MSCAN_CANE 0x80 -#define MSCAN_CLKSRC 0x40 -#define MSCAN_LOOPB 0x20 -#define MSCAN_LISTEN 0x10 -#define MSCAN_WUPM 0x04 -#define MSCAN_SLPAK 0x02 -#define MSCAN_INITAK 0x01 - -/* Use the MPC5200 MSCAN variant? */ -#ifdef CONFIG_PPC -#define MSCAN_FOR_MPC5200 -#endif - -#ifdef MSCAN_FOR_MPC5200 -#define MSCAN_CLKSRC_BUS 0 -#define MSCAN_CLKSRC_XTAL MSCAN_CLKSRC -#else -#define MSCAN_CLKSRC_BUS MSCAN_CLKSRC -#define MSCAN_CLKSRC_XTAL 0 -#endif - -/* MSCAN receiver flag register (CANRFLG) bits */ -#define MSCAN_WUPIF 0x80 -#define MSCAN_CSCIF 0x40 -#define MSCAN_RSTAT1 0x20 -#define MSCAN_RSTAT0 0x10 -#define MSCAN_TSTAT1 0x08 -#define MSCAN_TSTAT0 0x04 -#define MSCAN_OVRIF 0x02 -#define MSCAN_RXF 0x01 -#define MSCAN_ERR_IF (MSCAN_OVRIF | MSCAN_CSCIF) -#define MSCAN_RSTAT_MSK (MSCAN_RSTAT1 | MSCAN_RSTAT0) -#define MSCAN_TSTAT_MSK (MSCAN_TSTAT1 | MSCAN_TSTAT0) -#define MSCAN_STAT_MSK (MSCAN_RSTAT_MSK | MSCAN_TSTAT_MSK) - -#define MSCAN_STATE_BUS_OFF (MSCAN_RSTAT1 | MSCAN_RSTAT0 | \ - MSCAN_TSTAT1 | MSCAN_TSTAT0) -#define MSCAN_STATE_TX(canrflg) (((canrflg)&MSCAN_TSTAT_MSK)>>2) -#define MSCAN_STATE_RX(canrflg) (((canrflg)&MSCAN_RSTAT_MSK)>>4) -#define MSCAN_STATE_ACTIVE 0 -#define MSCAN_STATE_WARNING 1 -#define MSCAN_STATE_PASSIVE 2 -#define MSCAN_STATE_BUSOFF 3 - -/* MSCAN receiver interrupt enable register (CANRIER) bits */ -#define MSCAN_WUPIE 0x80 -#define MSCAN_CSCIE 0x40 -#define MSCAN_RSTATE1 0x20 -#define MSCAN_RSTATE0 0x10 -#define MSCAN_TSTATE1 0x08 -#define MSCAN_TSTATE0 0x04 -#define MSCAN_OVRIE 0x02 -#define MSCAN_RXFIE 0x01 - -/* MSCAN transmitter flag register (CANTFLG) bits */ -#define MSCAN_TXE2 0x04 -#define MSCAN_TXE1 0x02 -#define MSCAN_TXE0 0x01 -#define MSCAN_TXE (MSCAN_TXE2 | MSCAN_TXE1 | MSCAN_TXE0) - -/* MSCAN transmitter interrupt enable register (CANTIER) bits */ -#define MSCAN_TXIE2 0x04 -#define MSCAN_TXIE1 0x02 -#define MSCAN_TXIE0 0x01 -#define MSCAN_TXIE (MSCAN_TXIE2 | MSCAN_TXIE1 | MSCAN_TXIE0) - -/* MSCAN transmitter message abort request (CANTARQ) bits */ -#define MSCAN_ABTRQ2 0x04 -#define MSCAN_ABTRQ1 0x02 -#define MSCAN_ABTRQ0 0x01 - -/* MSCAN transmitter message abort ack (CANTAAK) bits */ -#define MSCAN_ABTAK2 0x04 -#define MSCAN_ABTAK1 0x02 -#define MSCAN_ABTAK0 0x01 - -/* MSCAN transmit buffer selection (CANTBSEL) bits */ -#define MSCAN_TX2 0x04 -#define MSCAN_TX1 0x02 -#define MSCAN_TX0 0x01 - -/* MSCAN ID acceptance control register (CANIDAC) bits */ -#define MSCAN_IDAM1 0x20 -#define MSCAN_IDAM0 0x10 -#define MSCAN_IDHIT2 0x04 -#define MSCAN_IDHIT1 0x02 -#define MSCAN_IDHIT0 0x01 - -#define MSCAN_AF_32BIT 0x00 -#define MSCAN_AF_16BIT MSCAN_IDAM0 -#define MSCAN_AF_8BIT MSCAN_IDAM1 -#define MSCAN_AF_CLOSED (MSCAN_IDAM0|MSCAN_IDAM1) -#define MSCAN_AF_MASK (~(MSCAN_IDAM0|MSCAN_IDAM1)) - -/* MSCAN Miscellaneous Register (CANMISC) bits */ -#define MSCAN_BOHOLD 0x01 - -#ifdef MSCAN_FOR_MPC5200 -#define _MSCAN_RESERVED_(n, num) u8 _res##n[num] -#define _MSCAN_RESERVED_DSR_SIZE 2 -#else -#define _MSCAN_RESERVED_(n, num) -#define _MSCAN_RESERVED_DSR_SIZE 0 -#endif - -/* Structure of the hardware registers */ -struct mscan_regs { - /* (see doc S12MSCANV3/D) MPC5200 MSCAN */ - u8 canctl0; /* + 0x00 0x00 */ - u8 canctl1; /* + 0x01 0x01 */ - _MSCAN_RESERVED_(1, 2); /* + 0x02 */ - u8 canbtr0; /* + 0x04 0x02 */ - u8 canbtr1; /* + 0x05 0x03 */ - _MSCAN_RESERVED_(2, 2); /* + 0x06 */ - u8 canrflg; /* + 0x08 0x04 */ - u8 canrier; /* + 0x09 0x05 */ - _MSCAN_RESERVED_(3, 2); /* + 0x0a */ - u8 cantflg; /* + 0x0c 0x06 */ - u8 cantier; /* + 0x0d 0x07 */ - _MSCAN_RESERVED_(4, 2); /* + 0x0e */ - u8 cantarq; /* + 0x10 0x08 */ - u8 cantaak; /* + 0x11 0x09 */ - _MSCAN_RESERVED_(5, 2); /* + 0x12 */ - u8 cantbsel; /* + 0x14 0x0a */ - u8 canidac; /* + 0x15 0x0b */ - u8 reserved; /* + 0x16 0x0c */ - _MSCAN_RESERVED_(6, 5); /* + 0x17 */ -#ifndef MSCAN_FOR_MPC5200 - u8 canmisc; /* 0x0d */ -#endif - u8 canrxerr; /* + 0x1c 0x0e */ - u8 cantxerr; /* + 0x1d 0x0f */ - _MSCAN_RESERVED_(7, 2); /* + 0x1e */ - u16 canidar1_0; /* + 0x20 0x10 */ - _MSCAN_RESERVED_(8, 2); /* + 0x22 */ - u16 canidar3_2; /* + 0x24 0x12 */ - _MSCAN_RESERVED_(9, 2); /* + 0x26 */ - u16 canidmr1_0; /* + 0x28 0x14 */ - _MSCAN_RESERVED_(10, 2); /* + 0x2a */ - u16 canidmr3_2; /* + 0x2c 0x16 */ - _MSCAN_RESERVED_(11, 2); /* + 0x2e */ - u16 canidar5_4; /* + 0x30 0x18 */ - _MSCAN_RESERVED_(12, 2); /* + 0x32 */ - u16 canidar7_6; /* + 0x34 0x1a */ - _MSCAN_RESERVED_(13, 2); /* + 0x36 */ - u16 canidmr5_4; /* + 0x38 0x1c */ - _MSCAN_RESERVED_(14, 2); /* + 0x3a */ - u16 canidmr7_6; /* + 0x3c 0x1e */ - _MSCAN_RESERVED_(15, 2); /* + 0x3e */ - struct { - u16 idr1_0; /* + 0x40 0x20 */ - _MSCAN_RESERVED_(16, 2); /* + 0x42 */ - u16 idr3_2; /* + 0x44 0x22 */ - _MSCAN_RESERVED_(17, 2); /* + 0x46 */ - u16 dsr1_0; /* + 0x48 0x24 */ - _MSCAN_RESERVED_(18, 2); /* + 0x4a */ - u16 dsr3_2; /* + 0x4c 0x26 */ - _MSCAN_RESERVED_(19, 2); /* + 0x4e */ - u16 dsr5_4; /* + 0x50 0x28 */ - _MSCAN_RESERVED_(20, 2); /* + 0x52 */ - u16 dsr7_6; /* + 0x54 0x2a */ - _MSCAN_RESERVED_(21, 2); /* + 0x56 */ - u8 dlr; /* + 0x58 0x2c */ - u8:8; /* + 0x59 0x2d */ - _MSCAN_RESERVED_(22, 2); /* + 0x5a */ - u16 time; /* + 0x5c 0x2e */ - } rx; - _MSCAN_RESERVED_(23, 2); /* + 0x5e */ - struct { - u16 idr1_0; /* + 0x60 0x30 */ - _MSCAN_RESERVED_(24, 2); /* + 0x62 */ - u16 idr3_2; /* + 0x64 0x32 */ - _MSCAN_RESERVED_(25, 2); /* + 0x66 */ - u16 dsr1_0; /* + 0x68 0x34 */ - _MSCAN_RESERVED_(26, 2); /* + 0x6a */ - u16 dsr3_2; /* + 0x6c 0x36 */ - _MSCAN_RESERVED_(27, 2); /* + 0x6e */ - u16 dsr5_4; /* + 0x70 0x38 */ - _MSCAN_RESERVED_(28, 2); /* + 0x72 */ - u16 dsr7_6; /* + 0x74 0x3a */ - _MSCAN_RESERVED_(29, 2); /* + 0x76 */ - u8 dlr; /* + 0x78 0x3c */ - u8 tbpr; /* + 0x79 0x3d */ - _MSCAN_RESERVED_(30, 2); /* + 0x7a */ - u16 time; /* + 0x7c 0x3e */ - } tx; - _MSCAN_RESERVED_(31, 2); /* + 0x7e */ -} __attribute__ ((packed)); - -#undef _MSCAN_RESERVED_ -#define MSCAN_REGION sizeof(struct mscan) - -#define TX_QUEUE_SIZE 3 - -struct tx_queue_entry { - struct list_head list; - u8 mask; - u8 id; -}; - -struct mscan_priv { - struct can_priv can; /* must be the first member */ - long open_time; - unsigned long flags; - void __iomem *reg_base; /* ioremap'ed address to registers */ - u8 shadow_statflg; - u8 shadow_canrier; - u8 cur_pri; - u8 prev_buf_id; - u8 tx_active; - - struct list_head tx_head; - struct tx_queue_entry tx_queue[TX_QUEUE_SIZE]; - struct napi_struct napi; -}; - -struct net_device *alloc_mscandev(void); -/* - * clock_src: - * 1 = The MSCAN clock source is the onchip Bus Clock. - * 0 = The MSCAN clock source is the chip Oscillator Clock. - */ -extern int register_mscandev(struct net_device *dev, int clock_src); -extern void unregister_mscandev(struct net_device *dev); - -#endif /* __MSCAN_H__ */ diff --git a/trunk/drivers/net/can/usb/ems_usb.c b/trunk/drivers/net/can/usb/ems_usb.c index 3e4419054c81..3685f3e42d12 100644 --- a/trunk/drivers/net/can/usb/ems_usb.c +++ b/trunk/drivers/net/can/usb/ems_usb.c @@ -315,7 +315,7 @@ static void ems_usb_rx_can_msg(struct ems_usb *dev, struct ems_cpc_msg *msg) if (skb == NULL) return; - cf->can_id = le32_to_cpu(msg->msg.can_msg.id); + cf->can_id = msg->msg.can_msg.id; cf->can_dlc = min_t(u8, msg->msg.can_msg.length, 8); if (msg->type == CPC_MSG_TYPE_EXT_CAN_FRAME @@ -801,9 +801,6 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne msg->length = CPC_CAN_MSG_MIN_SIZE + cf->can_dlc; } - /* Respect byte order */ - msg->msg.can_msg.id = cpu_to_le32(msg->msg.can_msg.id); - for (i = 0; i < MAX_TX_URBS; i++) { if (dev->tx_contexts[i].echo_index == MAX_TX_URBS) { context = &dev->tx_contexts[i]; diff --git a/trunk/drivers/net/cassini.c b/trunk/drivers/net/cassini.c index f857afe8e488..05916aafa4f1 100644 --- a/trunk/drivers/net/cassini.c +++ b/trunk/drivers/net/cassini.c @@ -4342,11 +4342,11 @@ static int cas_open(struct net_device *dev) cas_unlock_all_restore(cp, flags); } - err = -ENOMEM; if (cas_tx_tiny_alloc(cp) < 0) - goto err_unlock; + return -ENOMEM; /* alloc rx descriptors */ + err = -ENOMEM; if (cas_alloc_rxds(cp) < 0) goto err_tx_tiny; @@ -4386,7 +4386,6 @@ static int cas_open(struct net_device *dev) cas_free_rxds(cp); err_tx_tiny: cas_tx_tiny_free(cp); -err_unlock: mutex_unlock(&cp->pm_mutex); return err; } diff --git a/trunk/drivers/net/cxgb3/common.h b/trunk/drivers/net/cxgb3/common.h index 6ff356d4c7ab..1b2c305fb82b 100644 --- a/trunk/drivers/net/cxgb3/common.h +++ b/trunk/drivers/net/cxgb3/common.h @@ -125,9 +125,11 @@ enum { /* adapter interrupt-maintained statistics */ IRQ_NUM_STATS /* keep last */ }; -#define TP_VERSION_MAJOR 1 -#define TP_VERSION_MINOR 1 -#define TP_VERSION_MICRO 0 +enum { + TP_VERSION_MAJOR = 1, + TP_VERSION_MINOR = 1, + TP_VERSION_MICRO = 0 +}; #define S_TP_VERSION_MAJOR 16 #define M_TP_VERSION_MAJOR 0xFF diff --git a/trunk/drivers/net/cxgb3/cxgb3_main.c b/trunk/drivers/net/cxgb3/cxgb3_main.c index b1a5a00a78cd..c9113d3297ee 100644 --- a/trunk/drivers/net/cxgb3/cxgb3_main.c +++ b/trunk/drivers/net/cxgb3/cxgb3_main.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include "common.h" @@ -993,21 +992,11 @@ static int bind_qsets(struct adapter *adap) return err; } -#define FW_VERSION __stringify(FW_VERSION_MAJOR) "." \ - __stringify(FW_VERSION_MINOR) "." __stringify(FW_VERSION_MICRO) -#define FW_FNAME "cxgb3/t3fw-" FW_VERSION ".bin" -#define TPSRAM_VERSION __stringify(TP_VERSION_MAJOR) "." \ - __stringify(TP_VERSION_MINOR) "." __stringify(TP_VERSION_MICRO) -#define TPSRAM_NAME "cxgb3/t3%c_psram-" TPSRAM_VERSION ".bin" +#define FW_FNAME "cxgb3/t3fw-%d.%d.%d.bin" +#define TPSRAM_NAME "cxgb3/t3%c_psram-%d.%d.%d.bin" #define AEL2005_OPT_EDC_NAME "cxgb3/ael2005_opt_edc.bin" #define AEL2005_TWX_EDC_NAME "cxgb3/ael2005_twx_edc.bin" #define AEL2020_TWX_EDC_NAME "cxgb3/ael2020_twx_edc.bin" -MODULE_FIRMWARE(FW_FNAME); -MODULE_FIRMWARE("cxgb3/t3b_psram-" TPSRAM_VERSION ".bin"); -MODULE_FIRMWARE("cxgb3/t3c_psram-" TPSRAM_VERSION ".bin"); -MODULE_FIRMWARE(AEL2005_OPT_EDC_NAME); -MODULE_FIRMWARE(AEL2005_TWX_EDC_NAME); -MODULE_FIRMWARE(AEL2020_TWX_EDC_NAME); static inline const char *get_edc_fw_name(int edc_idx) { @@ -1078,13 +1067,16 @@ int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size) static int upgrade_fw(struct adapter *adap) { int ret; + char buf[64]; const struct firmware *fw; struct device *dev = &adap->pdev->dev; - ret = request_firmware(&fw, FW_FNAME, dev); + snprintf(buf, sizeof(buf), FW_FNAME, FW_VERSION_MAJOR, + FW_VERSION_MINOR, FW_VERSION_MICRO); + ret = request_firmware(&fw, buf, dev); if (ret < 0) { dev_err(dev, "could not upgrade firmware: unable to load %s\n", - FW_FNAME); + buf); return ret; } ret = t3_load_fw(adap, fw->data, fw->size); @@ -1128,7 +1120,8 @@ static int update_tpsram(struct adapter *adap) if (!rev) return 0; - snprintf(buf, sizeof(buf), TPSRAM_NAME, rev); + snprintf(buf, sizeof(buf), TPSRAM_NAME, rev, + TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO); ret = request_firmware(&tpsram, buf, dev); if (ret < 0) { diff --git a/trunk/drivers/net/davinci_emac.c b/trunk/drivers/net/davinci_emac.c index 79ce8e857eab..f1b09c0992b4 100644 --- a/trunk/drivers/net/davinci_emac.c +++ b/trunk/drivers/net/davinci_emac.c @@ -2217,7 +2217,7 @@ void emac_poll_controller(struct net_device *ndev) struct emac_priv *priv = netdev_priv(ndev); emac_int_disable(priv); - emac_irq(ndev->irq, ndev); + emac_irq(ndev->irq, priv); emac_int_enable(priv); } #endif diff --git a/trunk/drivers/net/dm9000.c b/trunk/drivers/net/dm9000.c index 3aab2e466008..31b8bef49d2e 100644 --- a/trunk/drivers/net/dm9000.c +++ b/trunk/drivers/net/dm9000.c @@ -100,7 +100,6 @@ typedef struct board_info { unsigned int flags; unsigned int in_suspend :1; - unsigned int wake_supported :1; int debug_level; enum dm9000_type type; @@ -117,8 +116,6 @@ typedef struct board_info { struct resource *data_req; struct resource *irq_res; - int irq_wake; - struct mutex addr_lock; /* phy and eeprom access lock */ struct delayed_work phy_poll; @@ -128,7 +125,6 @@ typedef struct board_info { struct mii_if_info mii; u32 msg_enable; - u32 wake_state; int rx_csum; int can_csum; @@ -572,54 +568,6 @@ static int dm9000_set_eeprom(struct net_device *dev, return 0; } -static void dm9000_get_wol(struct net_device *dev, struct ethtool_wolinfo *w) -{ - board_info_t *dm = to_dm9000_board(dev); - - memset(w, 0, sizeof(struct ethtool_wolinfo)); - - /* note, we could probably support wake-phy too */ - w->supported = dm->wake_supported ? WAKE_MAGIC : 0; - w->wolopts = dm->wake_state; -} - -static int dm9000_set_wol(struct net_device *dev, struct ethtool_wolinfo *w) -{ - board_info_t *dm = to_dm9000_board(dev); - unsigned long flags; - u32 opts = w->wolopts; - u32 wcr = 0; - - if (!dm->wake_supported) - return -EOPNOTSUPP; - - if (opts & ~WAKE_MAGIC) - return -EINVAL; - - if (opts & WAKE_MAGIC) - wcr |= WCR_MAGICEN; - - mutex_lock(&dm->addr_lock); - - spin_lock_irqsave(&dm->lock, flags); - iow(dm, DM9000_WCR, wcr); - spin_unlock_irqrestore(&dm->lock, flags); - - mutex_unlock(&dm->addr_lock); - - if (dm->wake_state != opts) { - /* change in wol state, update IRQ state */ - - if (!dm->wake_state) - set_irq_wake(dm->irq_wake, 1); - else if (dm->wake_state & !opts) - set_irq_wake(dm->irq_wake, 0); - } - - dm->wake_state = opts; - return 0; -} - static const struct ethtool_ops dm9000_ethtool_ops = { .get_drvinfo = dm9000_get_drvinfo, .get_settings = dm9000_get_settings, @@ -628,8 +576,6 @@ static const struct ethtool_ops dm9000_ethtool_ops = { .set_msglevel = dm9000_set_msglevel, .nway_reset = dm9000_nway_reset, .get_link = dm9000_get_link, - .get_wol = dm9000_get_wol, - .set_wol = dm9000_set_wol, .get_eeprom_len = dm9000_get_eeprom_len, .get_eeprom = dm9000_get_eeprom, .set_eeprom = dm9000_set_eeprom, @@ -776,7 +722,6 @@ dm9000_init_dm9000(struct net_device *dev) { board_info_t *db = netdev_priv(dev); unsigned int imr; - unsigned int ncr; dm9000_dbg(db, 1, "entering %s\n", __func__); @@ -791,15 +736,8 @@ dm9000_init_dm9000(struct net_device *dev) iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ iow(db, DM9000_GPR, 0); /* Enable PHY */ - ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0; - - /* if wol is needed, then always set NCR_WAKEEN otherwise we end - * up dumping the wake events if we disable this. There is already - * a wake-mask in DM9000_WCR */ - if (db->wake_supported) - ncr |= NCR_WAKEEN; - - iow(db, DM9000_NCR, ncr); + if (db->flags & DM9000_PLATF_EXT_PHY) + iow(db, DM9000_NCR, NCR_EXT_PHY); /* Program operating register */ iow(db, DM9000_TCR, 0); /* TX Polling clear */ @@ -1107,41 +1045,6 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t dm9000_wol_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - board_info_t *db = netdev_priv(dev); - unsigned long flags; - unsigned nsr, wcr; - - spin_lock_irqsave(&db->lock, flags); - - nsr = ior(db, DM9000_NSR); - wcr = ior(db, DM9000_WCR); - - dev_dbg(db->dev, "%s: NSR=0x%02x, WCR=0x%02x\n", __func__, nsr, wcr); - - if (nsr & NSR_WAKEST) { - /* clear, so we can avoid */ - iow(db, DM9000_NSR, NSR_WAKEST); - - if (wcr & WCR_LINKST) - dev_info(db->dev, "wake by link status change\n"); - if (wcr & WCR_SAMPLEST) - dev_info(db->dev, "wake by sample packet\n"); - if (wcr & WCR_MAGICST ) - dev_info(db->dev, "wake by magic packet\n"); - if (!(wcr & (WCR_LINKST | WCR_SAMPLEST | WCR_MAGICST))) - dev_err(db->dev, "wake signalled with no reason? " - "NSR=0x%02x, WSR=0x%02x\n", nsr, wcr); - - } - - spin_unlock_irqrestore(&db->lock, flags); - - return (nsr & NSR_WAKEST) ? IRQ_HANDLED : IRQ_NONE; -} - #ifdef CONFIG_NET_POLL_CONTROLLER /* *Used by netconsole @@ -1396,29 +1299,6 @@ dm9000_probe(struct platform_device *pdev) goto out; } - db->irq_wake = platform_get_irq(pdev, 1); - if (db->irq_wake >= 0) { - dev_dbg(db->dev, "wakeup irq %d\n", db->irq_wake); - - ret = request_irq(db->irq_wake, dm9000_wol_interrupt, - IRQF_SHARED, dev_name(db->dev), ndev); - if (ret) { - dev_err(db->dev, "cannot get wakeup irq (%d)\n", ret); - } else { - - /* test to see if irq is really wakeup capable */ - ret = set_irq_wake(db->irq_wake, 1); - if (ret) { - dev_err(db->dev, "irq %d cannot set wakeup (%d)\n", - db->irq_wake, ret); - ret = 0; - } else { - set_irq_wake(db->irq_wake, 0); - db->wake_supported = 1; - } - } - } - iosize = resource_size(db->addr_res); db->addr_req = request_mem_region(db->addr_res->start, iosize, pdev->name); @@ -1610,14 +1490,10 @@ dm9000_drv_suspend(struct device *dev) db = netdev_priv(ndev); db->in_suspend = 1; - if (!netif_running(ndev)) - return 0; - - netif_device_detach(ndev); - - /* only shutdown if not using WoL */ - if (!db->wake_state) + if (netif_running(ndev)) { + netif_device_detach(ndev); dm9000_shutdown(ndev); + } } return 0; } @@ -1630,13 +1506,10 @@ dm9000_drv_resume(struct device *dev) board_info_t *db = netdev_priv(ndev); if (ndev) { + if (netif_running(ndev)) { - /* reset if we were not in wake mode to ensure if - * the device was powered off it is in a known state */ - if (!db->wake_state) { - dm9000_reset(db); - dm9000_init_dm9000(ndev); - } + dm9000_reset(db); + dm9000_init_dm9000(ndev); netif_device_attach(ndev); } diff --git a/trunk/drivers/net/dm9000.h b/trunk/drivers/net/dm9000.h index 55688bd1a3ef..fb1c924d79b4 100644 --- a/trunk/drivers/net/dm9000.h +++ b/trunk/drivers/net/dm9000.h @@ -111,13 +111,6 @@ #define RSR_CE (1<<1) #define RSR_FOE (1<<0) -#define WCR_LINKEN (1 << 5) -#define WCR_SAMPLEEN (1 << 4) -#define WCR_MAGICEN (1 << 3) -#define WCR_LINKST (1 << 2) -#define WCR_SAMPLEST (1 << 1) -#define WCR_MAGICST (1 << 0) - #define FCTR_HWOT(ot) (( ot & 0xf ) << 4 ) #define FCTR_LWOT(ot) ( ot & 0xf ) diff --git a/trunk/drivers/net/e100.c b/trunk/drivers/net/e100.c index 7462fdfd7f92..f428c5f72f18 100644 --- a/trunk/drivers/net/e100.c +++ b/trunk/drivers/net/e100.c @@ -1438,31 +1438,19 @@ static int e100_phy_init(struct nic *nic) } else DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); + /* Isolate all the PHY ids */ + for (addr = 0; addr < 32; addr++) + mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); + /* Select the discovered PHY */ + bmcr &= ~BMCR_ISOLATE; + mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); + /* Get phy ID */ id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); nic->phy = (u32)id_hi << 16 | (u32)id_lo; DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); - /* Select the phy and isolate the rest */ - for (addr = 0; addr < 32; addr++) { - if (addr != nic->mii.phy_id) { - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - } else if (nic->phy != phy_82552_v) { - bmcr = mdio_read(netdev, addr, MII_BMCR); - mdio_write(netdev, addr, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - } - } - /* - * Workaround for 82552: - * Clear the ISOLATE bit on selected phy_id last (mirrored on all - * other phy_id's) using bmcr value from addr discovery loop above. - */ - if (nic->phy == phy_82552_v) - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, - bmcr & ~BMCR_ISOLATE); - /* Handle National tx phys */ #define NCS_PHY_MODEL_MASK 0xFFF0FFFF if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { diff --git a/trunk/drivers/net/e1000e/defines.h b/trunk/drivers/net/e1000e/defines.h index 1190167a8b3d..c0f185beb8bc 100644 --- a/trunk/drivers/net/e1000e/defines.h +++ b/trunk/drivers/net/e1000e/defines.h @@ -76,7 +76,6 @@ /* Extended Device Control */ #define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ -#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ #define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ #define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */ #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 @@ -348,7 +347,6 @@ /* Extended Configuration Control and Size */ #define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 #define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 -#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008 #define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16 diff --git a/trunk/drivers/net/e1000e/e1000.h b/trunk/drivers/net/e1000e/e1000.h index 00989c5534c1..08a4f9dd20e9 100644 --- a/trunk/drivers/net/e1000e/e1000.h +++ b/trunk/drivers/net/e1000e/e1000.h @@ -141,20 +141,6 @@ struct e1000_info; #define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */ #define HV_TNCRS_LOWER PHY_REG(778, 30) -/* BM PHY Copper Specific Status */ -#define BM_CS_STATUS 17 -#define BM_CS_STATUS_LINK_UP 0x0400 -#define BM_CS_STATUS_RESOLVED 0x0800 -#define BM_CS_STATUS_SPEED_MASK 0xC000 -#define BM_CS_STATUS_SPEED_1000 0x8000 - -/* 82577 Mobile Phy Status Register */ -#define HV_M_STATUS 26 -#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000 -#define HV_M_STATUS_SPEED_MASK 0x0300 -#define HV_M_STATUS_SPEED_1000 0x0200 -#define HV_M_STATUS_LINK_UP 0x0040 - enum e1000_boards { board_82571, board_82572, diff --git a/trunk/drivers/net/e1000e/hw.h b/trunk/drivers/net/e1000e/hw.h index aaea41ef794d..7b05cf47f7f5 100644 --- a/trunk/drivers/net/e1000e/hw.h +++ b/trunk/drivers/net/e1000e/hw.h @@ -903,7 +903,6 @@ struct e1000_shadow_ram { struct e1000_dev_spec_ich8lan { bool kmrn_lock_loss_workaround_enabled; struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS]; - bool nvm_k1_enabled; }; struct e1000_hw { diff --git a/trunk/drivers/net/e1000e/ich8lan.c b/trunk/drivers/net/e1000e/ich8lan.c index 51ddb04ab195..b6388b9535fd 100644 --- a/trunk/drivers/net/e1000e/ich8lan.c +++ b/trunk/drivers/net/e1000e/ich8lan.c @@ -124,25 +124,11 @@ #define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in milliseconds */ -/* SMBus Address Phy Register */ -#define HV_SMB_ADDR PHY_REG(768, 26) -#define HV_SMB_ADDR_PEC_EN 0x0200 -#define HV_SMB_ADDR_VALID 0x0080 - -/* Strapping Option Register - RO */ -#define E1000_STRAP 0x0000C -#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000 -#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17 - /* OEM Bits Phy Register */ #define HV_OEM_BITS PHY_REG(768, 25) #define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */ -#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ #define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ -#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ -#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ - /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ /* Offset 04h HSFSTS */ union ich8_hws_flash_status { @@ -222,9 +208,6 @@ static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw); static s32 e1000_led_on_pchlan(struct e1000_hw *hw); static s32 e1000_led_off_pchlan(struct e1000_hw *hw); static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); -static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); -static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); -static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) { @@ -500,6 +483,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) goto out; } + if (hw->mac.type == e1000_pchlan) { + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_K1_CONFIG, + E1000_KMRNCTRLSTA_K1_ENABLE); + if (ret_val) + goto out; + } + /* * First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex @@ -509,12 +500,6 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (ret_val) goto out; - if (hw->mac.type == e1000_pchlan) { - ret_val = e1000_k1_gig_workaround_hv(hw, link); - if (ret_val) - goto out; - } - if (!link) goto out; /* No link detected */ @@ -808,326 +793,6 @@ static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw) return 0; } -/** - * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration - * @hw: pointer to the HW structure - * - * SW should configure the LCD from the NVM extended configuration region - * as a workaround for certain parts. - **/ -static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; - s32 ret_val; - u16 word_addr, reg_data, reg_addr, phy_page = 0; - - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - return ret_val; - - /* - * Initialize the PHY from the NVM on ICH platforms. This - * is needed due to an issue where the NVM configuration is - * not properly autoloaded after power transitions. - * Therefore, after each PHY reset, we will load the - * configuration data out of the NVM manually. - */ - if ((hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) || - (hw->mac.type == e1000_pchlan)) { - struct e1000_adapter *adapter = hw->adapter; - - /* Check if SW needs to configure the PHY */ - if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) || - (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M) || - (hw->mac.type == e1000_pchlan)) - sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; - else - sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; - - data = er32(FEXTNVM); - if (!(data & sw_cfg_mask)) - goto out; - - /* Wait for basic configuration completes before proceeding */ - e1000_lan_init_done_ich8lan(hw); - - /* - * Make sure HW does not configure LCD from PHY - * extended configuration before SW configuration - */ - data = er32(EXTCNF_CTRL); - if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) - goto out; - - cnf_size = er32(EXTCNF_SIZE); - cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; - cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; - if (!cnf_size) - goto out; - - cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; - cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; - - if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && - (hw->mac.type == e1000_pchlan)) { - /* - * HW configures the SMBus address and LEDs when the - * OEM and LCD Write Enable bits are set in the NVM. - * When both NVM bits are cleared, SW will configure - * them instead. - */ - data = er32(STRAP); - data &= E1000_STRAP_SMBUS_ADDRESS_MASK; - reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT; - reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; - ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, - reg_data); - if (ret_val) - goto out; - - data = er32(LEDCTL); - ret_val = e1000_write_phy_reg_hv_locked(hw, - HV_LED_CONFIG, - (u16)data); - if (ret_val) - goto out; - } - /* Configure LCD from extended configuration region. */ - - /* cnf_base_addr is in DWORD */ - word_addr = (u16)(cnf_base_addr << 1); - - for (i = 0; i < cnf_size; i++) { - ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1, - ®_data); - if (ret_val) - goto out; - - ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1), - 1, ®_addr); - if (ret_val) - goto out; - - /* Save off the PHY page for future writes. */ - if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { - phy_page = reg_data; - continue; - } - - reg_addr &= PHY_REG_MASK; - reg_addr |= phy_page; - - ret_val = phy->ops.write_phy_reg_locked(hw, - (u32)reg_addr, - reg_data); - if (ret_val) - goto out; - } - } - -out: - hw->phy.ops.release_phy(hw); - return ret_val; -} - -/** - * e1000_k1_gig_workaround_hv - K1 Si workaround - * @hw: pointer to the HW structure - * @link: link up bool flag - * - * If K1 is enabled for 1Gbps, the MAC might stall when transitioning - * from a lower speed. This workaround disables K1 whenever link is at 1Gig - * If link is down, the function will restore the default K1 setting located - * in the NVM. - **/ -static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) -{ - s32 ret_val = 0; - u16 status_reg = 0; - bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled; - - if (hw->mac.type != e1000_pchlan) - goto out; - - /* Wrap the whole flow with the sw flag */ - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - goto out; - - /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */ - if (link) { - if (hw->phy.type == e1000_phy_82578) { - ret_val = hw->phy.ops.read_phy_reg_locked(hw, - BM_CS_STATUS, - &status_reg); - if (ret_val) - goto release; - - status_reg &= BM_CS_STATUS_LINK_UP | - BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_MASK; - - if (status_reg == (BM_CS_STATUS_LINK_UP | - BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_1000)) - k1_enable = false; - } - - if (hw->phy.type == e1000_phy_82577) { - ret_val = hw->phy.ops.read_phy_reg_locked(hw, - HV_M_STATUS, - &status_reg); - if (ret_val) - goto release; - - status_reg &= HV_M_STATUS_LINK_UP | - HV_M_STATUS_AUTONEG_COMPLETE | - HV_M_STATUS_SPEED_MASK; - - if (status_reg == (HV_M_STATUS_LINK_UP | - HV_M_STATUS_AUTONEG_COMPLETE | - HV_M_STATUS_SPEED_1000)) - k1_enable = false; - } - - /* Link stall fix for link up */ - ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19), - 0x0100); - if (ret_val) - goto release; - - } else { - /* Link stall fix for link down */ - ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19), - 0x4100); - if (ret_val) - goto release; - } - - ret_val = e1000_configure_k1_ich8lan(hw, k1_enable); - -release: - hw->phy.ops.release_phy(hw); -out: - return ret_val; -} - -/** - * e1000_configure_k1_ich8lan - Configure K1 power state - * @hw: pointer to the HW structure - * @enable: K1 state to configure - * - * Configure the K1 power state based on the provided parameter. - * Assumes semaphore already acquired. - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - **/ -static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) -{ - s32 ret_val = 0; - u32 ctrl_reg = 0; - u32 ctrl_ext = 0; - u32 reg = 0; - u16 kmrn_reg = 0; - - ret_val = e1000e_read_kmrn_reg_locked(hw, - E1000_KMRNCTRLSTA_K1_CONFIG, - &kmrn_reg); - if (ret_val) - goto out; - - if (k1_enable) - kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE; - else - kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE; - - ret_val = e1000e_write_kmrn_reg_locked(hw, - E1000_KMRNCTRLSTA_K1_CONFIG, - kmrn_reg); - if (ret_val) - goto out; - - udelay(20); - ctrl_ext = er32(CTRL_EXT); - ctrl_reg = er32(CTRL); - - reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - reg |= E1000_CTRL_FRCSPD; - ew32(CTRL, reg); - - ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS); - udelay(20); - ew32(CTRL, ctrl_reg); - ew32(CTRL_EXT, ctrl_ext); - udelay(20); - -out: - return ret_val; -} - -/** - * e1000_oem_bits_config_ich8lan - SW-based LCD Configuration - * @hw: pointer to the HW structure - * @d0_state: boolean if entering d0 or d3 device state - * - * SW will configure Gbe Disable and LPLU based on the NVM. The four bits are - * collectively called OEM bits. The OEM Write Enable bit and SW Config bit - * in NVM determines whether HW should configure LPLU and Gbe Disable. - **/ -static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) -{ - s32 ret_val = 0; - u32 mac_reg; - u16 oem_reg; - - if (hw->mac.type != e1000_pchlan) - return ret_val; - - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - return ret_val; - - mac_reg = er32(EXTCNF_CTRL); - if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) - goto out; - - mac_reg = er32(FEXTNVM); - if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M)) - goto out; - - mac_reg = er32(PHY_CTRL); - - ret_val = hw->phy.ops.read_phy_reg_locked(hw, HV_OEM_BITS, &oem_reg); - if (ret_val) - goto out; - - oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU); - - if (d0_state) { - if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE) - oem_reg |= HV_OEM_BITS_GBE_DIS; - - if (mac_reg & E1000_PHY_CTRL_D0A_LPLU) - oem_reg |= HV_OEM_BITS_LPLU; - } else { - if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE) - oem_reg |= HV_OEM_BITS_GBE_DIS; - - if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU) - oem_reg |= HV_OEM_BITS_LPLU; - } - /* Restart auto-neg to activate the bits */ - oem_reg |= HV_OEM_BITS_RESTART_AN; - ret_val = hw->phy.ops.write_phy_reg_locked(hw, HV_OEM_BITS, oem_reg); - -out: - hw->phy.ops.release_phy(hw); - - return ret_val; -} - - /** * e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be * done after every PHY reset. @@ -1168,20 +833,10 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) ret_val = hw->phy.ops.acquire_phy(hw); if (ret_val) return ret_val; - hw->phy.addr = 1; - ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); - if (ret_val) - goto out; + e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); hw->phy.ops.release_phy(hw); - /* - * Configure the K1 Si workaround during phy reset assuming there is - * link so that it disables K1 if link is in 1Gbps. - */ - ret_val = e1000_k1_gig_workaround_hv(hw, true); - -out: return ret_val; } @@ -1227,8 +882,11 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) **/ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) { - s32 ret_val = 0; - u16 reg; + struct e1000_phy_info *phy = &hw->phy; + u32 i; + u32 data, cnf_size, cnf_base_addr, sw_cfg_mask; + s32 ret_val; + u16 reg, word_addr, reg_data, reg_addr, phy_page = 0; ret_val = e1000e_phy_hw_reset_generic(hw); if (ret_val) @@ -1247,16 +905,81 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) if (hw->mac.type == e1000_pchlan) e1e_rphy(hw, BM_WUC, ®); - /* Configure the LCD with the extended configuration region in NVM */ - ret_val = e1000_sw_lcd_config_ich8lan(hw); - if (ret_val) - goto out; + /* + * Initialize the PHY from the NVM on ICH platforms. This + * is needed due to an issue where the NVM configuration is + * not properly autoloaded after power transitions. + * Therefore, after each PHY reset, we will load the + * configuration data out of the NVM manually. + */ + if (hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) { + struct e1000_adapter *adapter = hw->adapter; - /* Configure the LCD with the OEM bits in NVM */ - if (hw->mac.type == e1000_pchlan) - ret_val = e1000_oem_bits_config_ich8lan(hw, true); + /* Check if SW needs configure the PHY */ + if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) || + (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M)) + sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; + else + sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; + + data = er32(FEXTNVM); + if (!(data & sw_cfg_mask)) + return 0; + + /* Wait for basic configuration completes before proceeding */ + e1000_lan_init_done_ich8lan(hw); + + /* + * Make sure HW does not configure LCD from PHY + * extended configuration before SW configuration + */ + data = er32(EXTCNF_CTRL); + if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) + return 0; + + cnf_size = er32(EXTCNF_SIZE); + cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; + cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; + if (!cnf_size) + return 0; + + cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; + cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; + + /* Configure LCD from extended configuration region. */ + + /* cnf_base_addr is in DWORD */ + word_addr = (u16)(cnf_base_addr << 1); + + for (i = 0; i < cnf_size; i++) { + ret_val = e1000_read_nvm(hw, + (word_addr + i * 2), + 1, + ®_data); + if (ret_val) + return ret_val; + + ret_val = e1000_read_nvm(hw, + (word_addr + i * 2 + 1), + 1, + ®_addr); + if (ret_val) + return ret_val; + + /* Save off the PHY page for future writes. */ + if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { + phy_page = reg_data; + continue; + } + + reg_addr |= phy_page; + + ret_val = e1e_wphy(hw, (u32)reg_addr, reg_data); + if (ret_val) + return ret_val; + } + } -out: return 0; } @@ -2583,7 +2306,6 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) **/ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) { - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u16 reg; u32 ctrl, icr, kab; s32 ret_val; @@ -2619,18 +2341,6 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ew32(PBS, E1000_PBS_16K); } - if (hw->mac.type == e1000_pchlan) { - /* Save the NVM K1 bit setting*/ - ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, ®); - if (ret_val) - return ret_val; - - if (reg & E1000_NVM_K1_ENABLE) - dev_spec->nvm_k1_enabled = true; - else - dev_spec->nvm_k1_enabled = false; - } - ctrl = er32(CTRL); if (!e1000_check_reset_block(hw)) { @@ -2676,15 +2386,6 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) if (hw->mac.type == e1000_pchlan) e1e_rphy(hw, BM_WUC, ®); - ret_val = e1000_sw_lcd_config_ich8lan(hw); - if (ret_val) - goto out; - - if (hw->mac.type == e1000_pchlan) { - ret_val = e1000_oem_bits_config_ich8lan(hw, true); - if (ret_val) - goto out; - } /* * For PCH, this write will make sure that any noise * will be detected as a CRC error and be dropped rather than show up @@ -2703,7 +2404,6 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) if (hw->mac.type == e1000_pchlan) ret_val = e1000_hv_phy_workarounds_ich8lan(hw); -out: return ret_val; } @@ -3008,6 +2708,14 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, if (ret_val) return ret_val; + if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) { + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_K1_CONFIG, + E1000_KMRNCTRLSTA_K1_DISABLE); + if (ret_val) + return ret_val; + } + if ((hw->mac.type == e1000_ich8lan) && (hw->phy.type == e1000_phy_igp_3) && (*speed == SPEED_1000)) { diff --git a/trunk/drivers/net/e1000e/phy.c b/trunk/drivers/net/e1000e/phy.c index 03175b3a2c9e..f9d33ab05e97 100644 --- a/trunk/drivers/net/e1000e/phy.c +++ b/trunk/drivers/net/e1000e/phy.c @@ -95,6 +95,13 @@ static const u16 e1000_igp_2_cable_length_table[] = /* BM PHY Copper Specific Control 1 */ #define BM_CS_CTRL1 16 +/* BM PHY Copper Specific Status */ +#define BM_CS_STATUS 17 +#define BM_CS_STATUS_LINK_UP 0x0400 +#define BM_CS_STATUS_RESOLVED 0x0800 +#define BM_CS_STATUS_SPEED_MASK 0xC000 +#define BM_CS_STATUS_SPEED_1000 0x8000 + #define HV_MUX_DATA_CTRL PHY_REG(776, 16) #define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 #define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 @@ -556,7 +563,7 @@ s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) } /** - * e1000e_read_kmrn_reg_locked - Read kumeran register + * e1000_read_kmrn_reg_locked - Read kumeran register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data @@ -565,7 +572,7 @@ s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) * information retrieved is stored in data. * Assumes semaphore already acquired. **/ -s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) +s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) { return __e1000_read_kmrn_reg(hw, offset, data, true); } @@ -624,7 +631,7 @@ s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) } /** - * e1000e_write_kmrn_reg_locked - Write kumeran register + * e1000_write_kmrn_reg_locked - Write kumeran register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset @@ -632,7 +639,7 @@ s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) * Write the data to PHY register at the offset using the kumeran interface. * Assumes semaphore already acquired. **/ -s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) +s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) { return __e1000_write_kmrn_reg(hw, offset, data, true); } diff --git a/trunk/drivers/net/fsl_pq_mdio.c b/trunk/drivers/net/fsl_pq_mdio.c index 25fabb3eedc5..4065b7c01ecb 100644 --- a/trunk/drivers/net/fsl_pq_mdio.c +++ b/trunk/drivers/net/fsl_pq_mdio.c @@ -103,18 +103,13 @@ int fsl_pq_local_mdio_read(struct fsl_pq_mdio __iomem *regs, return value; } -static struct fsl_pq_mdio __iomem *fsl_pq_mdio_get_regs(struct mii_bus *bus) -{ - return (void __iomem __force *)bus->priv; -} - /* * Write value to the PHY at mii_id at register regnum, * on the bus, waiting until the write is done before returning. */ int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { - struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus); + struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv; /* Write to the local MII regs */ return(fsl_pq_local_mdio_write(regs, mii_id, regnum, value)); @@ -126,7 +121,7 @@ int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) */ int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { - struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus); + struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv; /* Read the local MII regs */ return(fsl_pq_local_mdio_read(regs, mii_id, regnum)); @@ -135,7 +130,7 @@ int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum) /* Reset the MIIM registers, and wait for the bus to free */ static int fsl_pq_mdio_reset(struct mii_bus *bus) { - struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus); + struct fsl_pq_mdio __iomem *regs = (void __iomem *)bus->priv; int timeout = PHY_INIT_TIMEOUT; mutex_lock(&bus->mdio_lock); @@ -267,11 +262,10 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, struct device_node *np = ofdev->node; struct device_node *tbi; struct fsl_pq_mdio __iomem *regs = NULL; - void __iomem *map; u32 __iomem *tbipa; struct mii_bus *new_bus; int tbiaddr = -1; - u64 addr = 0, size = 0; + u64 addr = 0, size = 0, ioremap_miimcfg = 0; int err = 0; new_bus = mdiobus_alloc(); @@ -285,19 +279,27 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, fsl_pq_mdio_bus_name(new_bus->id, np); /* Set the PHY base address */ - addr = of_translate_address(np, of_get_address(np, 0, &size, NULL)); - map = ioremap(addr, size); - if (!map) { - err = -ENOMEM; + if (of_device_is_compatible(np,"fsl,gianfar-mdio") || + of_device_is_compatible(np, "fsl,gianfar-tbi") || + of_device_is_compatible(np, "fsl,ucc-mdio") || + of_device_is_compatible(np,"ucc_geth_phy" )) { + addr = of_translate_address(np, of_get_address(np, 0, &size, NULL)); + ioremap_miimcfg = container_of(addr, struct fsl_pq_mdio, miimcfg); + regs = ioremap(ioremap_miimcfg, size + + offsetof(struct fsl_pq_mdio, miimcfg)); + } else if (of_device_is_compatible(np,"fsl,etsec2-mdio") || + of_device_is_compatible(np, "fsl,etsec2-tbi")) { + addr = of_translate_address(np, of_get_address(np, 0, &size, NULL)); + regs = ioremap(addr, size); + } else { + err = -EINVAL; goto err_free_bus; } - if (of_device_is_compatible(np, "fsl,gianfar-mdio") || - of_device_is_compatible(np, "fsl,gianfar-tbi") || - of_device_is_compatible(np, "fsl,ucc-mdio") || - of_device_is_compatible(np, "ucc_geth_phy")) - map -= offsetof(struct fsl_pq_mdio, miimcfg); - regs = map; + if (NULL == regs) { + err = -ENOMEM; + goto err_free_bus; + } new_bus->priv = (void __force *)regs; @@ -409,7 +411,7 @@ static int fsl_pq_mdio_remove(struct of_device *ofdev) dev_set_drvdata(device, NULL); - iounmap(fsl_pq_mdio_get_regs(bus)); + iounmap((void __iomem *)bus->priv); bus->priv = NULL; mdiobus_free(bus); @@ -462,4 +464,3 @@ void fsl_pq_mdio_exit(void) of_unregister_platform_driver(&fsl_pq_mdio_driver); } module_exit(fsl_pq_mdio_exit); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/net/gianfar.c b/trunk/drivers/net/gianfar.c index 16def131c390..086d40dd526d 100644 --- a/trunk/drivers/net/gianfar.c +++ b/trunk/drivers/net/gianfar.c @@ -327,7 +327,7 @@ static int gfar_alloc_skb_resources(struct net_device *ndev) static void gfar_init_tx_rx_base(struct gfar_private *priv) { struct gfar __iomem *regs = priv->gfargrp[0].regs; - u32 __iomem *baddr; + u32 *baddr; int i; baddr = ®s->tbase0; @@ -770,8 +770,7 @@ static unsigned int reverse_bitmap(unsigned int bit_map, unsigned int max_qs) return new_bit_map; } -static u32 cluster_entry_per_class(struct gfar_private *priv, u32 rqfar, - u32 class) +u32 cluster_entry_per_class(struct gfar_private *priv, u32 rqfar, u32 class) { u32 rqfpr = FPR_FILER_MASK; u32 rqfcr = 0x0; @@ -850,7 +849,7 @@ static int gfar_probe(struct of_device *ofdev, int len_devname; u32 rstat = 0, tstat = 0, rqueue = 0, tqueue = 0; u32 isrg = 0; - u32 __iomem *baddr; + u32 *baddr; err = gfar_of_init(ofdev, &dev); @@ -1246,7 +1245,7 @@ static int gfar_restore(struct device *dev) phy_start(priv->phydev); netif_device_attach(ndev); - enable_napi(priv); + napi_enable(&priv->gfargrp.napi); return 0; } @@ -1659,10 +1658,10 @@ void gfar_start(struct net_device *dev) } void gfar_configure_coalescing(struct gfar_private *priv, - unsigned long tx_mask, unsigned long rx_mask) + unsigned int tx_mask, unsigned int rx_mask) { struct gfar __iomem *regs = priv->gfargrp[0].regs; - u32 __iomem *baddr; + u32 *baddr; int i = 0; /* Backward compatible case ---- even if we enable @@ -1928,11 +1927,14 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) /* total number of fragments in the SKB */ nr_frags = skb_shinfo(skb)->nr_frags; + spin_lock_irqsave(&tx_queue->txlock, flags); + /* check if there is space to queue this packet */ if ((nr_frags+1) > tx_queue->num_txbdfree) { /* no space, stop the queue */ netif_tx_stop_queue(txq); dev->stats.tx_fifo_errors++; + spin_unlock_irqrestore(&tx_queue->txlock, flags); return NETDEV_TX_BUSY; } @@ -1995,20 +1997,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb); - /* - * We can work in parallel with gfar_clean_tx_ring(), except - * when modifying num_txbdfree. Note that we didn't grab the lock - * when we were reading the num_txbdfree and checking for available - * space, that's because outside of this function it can only grow, - * and once we've got needed space, it cannot suddenly disappear. - * - * The lock also protects us from gfar_error(), which can modify - * regs->tstat and thus retrigger the transfers, which is why we - * also must grab the lock before setting ready bit for the first - * to be transmitted BD. - */ - spin_lock_irqsave(&tx_queue->txlock, flags); - /* * The powerpc-specific eieio() is used, as wmb() has too strong * semantics (it requires synchronization between cacheable and @@ -2236,8 +2224,6 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) skb_dirtytx = tx_queue->skb_dirtytx; while ((skb = tx_queue->tx_skbuff[skb_dirtytx])) { - unsigned long flags; - frags = skb_shinfo(skb)->nr_frags; lbdp = skip_txbd(bdp, frags, base, tx_ring_size); @@ -2282,9 +2268,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) TX_RING_MOD_MASK(tx_ring_size); howmany++; - spin_lock_irqsave(&tx_queue->txlock, flags); tx_queue->num_txbdfree += frags + 1; - spin_unlock_irqrestore(&tx_queue->txlock, flags); } /* If we freed a buffer, we can restart transmission, if necessary */ @@ -2519,6 +2503,8 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) skb_put(skb, pkt_len); dev->stats.rx_bytes += pkt_len; + if (in_irq() || irqs_disabled()) + printk("Interrupt problem!\n"); gfar_process_frame(dev, skb, amount_pull); } else { @@ -2560,9 +2546,9 @@ static int gfar_poll(struct napi_struct *napi, int budget) struct gfar_priv_tx_q *tx_queue = NULL; struct gfar_priv_rx_q *rx_queue = NULL; int rx_cleaned = 0, budget_per_queue = 0, rx_cleaned_per_queue = 0; - int tx_cleaned = 0, i, left_over_budget = budget; - unsigned long serviced_queues = 0; + int tx_cleaned = 0, i, left_over_budget = budget, serviced_queues = 0; int num_queues = 0; + unsigned long flags; num_queues = gfargrp->num_rx_queues; budget_per_queue = budget/num_queues; @@ -2582,7 +2568,14 @@ static int gfar_poll(struct napi_struct *napi, int budget) rx_queue = priv->rx_queue[i]; tx_queue = priv->tx_queue[rx_queue->qindex]; - tx_cleaned += gfar_clean_tx_ring(tx_queue); + /* If we fail to get the lock, + * don't bother with the TX BDs */ + if (spin_trylock_irqsave(&tx_queue->txlock, flags)) { + tx_cleaned += gfar_clean_tx_ring(tx_queue); + spin_unlock_irqrestore(&tx_queue->txlock, + flags); + } + rx_cleaned_per_queue = gfar_clean_rx_ring(rx_queue, budget_per_queue); rx_cleaned += rx_cleaned_per_queue; @@ -2950,22 +2943,14 @@ static irqreturn_t gfar_error(int irq, void *grp_id) if (events & IEVENT_CRL) dev->stats.tx_aborted_errors++; if (events & IEVENT_XFUN) { - unsigned long flags; - if (netif_msg_tx_err(priv)) printk(KERN_DEBUG "%s: TX FIFO underrun, " "packet dropped.\n", dev->name); dev->stats.tx_dropped++; priv->extra_stats.tx_underrun++; - local_irq_save(flags); - lock_tx_qs(priv); - /* Reactivate the Tx Queues */ gfar_write(®s->tstat, gfargrp->tstat); - - unlock_tx_qs(priv); - local_irq_restore(flags); } if (netif_msg_tx_err(priv)) printk(KERN_DEBUG "%s: Transmit Error\n", dev->name); diff --git a/trunk/drivers/net/gianfar.h b/trunk/drivers/net/gianfar.h index cbb451011cb5..44b63daa7ff3 100644 --- a/trunk/drivers/net/gianfar.h +++ b/trunk/drivers/net/gianfar.h @@ -986,10 +986,10 @@ struct gfar_priv_grp { struct gfar_private *priv; struct gfar __iomem *regs; unsigned int grp_id; - unsigned long rx_bit_map; - unsigned long tx_bit_map; - unsigned long num_tx_queues; - unsigned long num_rx_queues; + unsigned int rx_bit_map; + unsigned int tx_bit_map; + unsigned int num_tx_queues; + unsigned int num_rx_queues; unsigned int rstat; unsigned int tstat; unsigned int imask; @@ -1118,7 +1118,7 @@ extern void gfar_halt(struct net_device *dev); extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, int enable, u32 regnum, u32 read); extern void gfar_configure_coalescing(struct gfar_private *priv, - unsigned long tx_mask, unsigned long rx_mask); + unsigned int tx_mask, unsigned int rx_mask); void gfar_init_sysfs(struct net_device *dev); extern const struct ethtool_ops gfar_ethtool_ops; diff --git a/trunk/drivers/net/gianfar_sysfs.c b/trunk/drivers/net/gianfar_sysfs.c index b31c9c8876e6..3724835d2856 100644 --- a/trunk/drivers/net/gianfar_sysfs.c +++ b/trunk/drivers/net/gianfar_sysfs.c @@ -186,7 +186,7 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev, temp = gfar_read(®s->attreli); temp &= ~ATTRELI_EI_MASK; temp |= ATTRELI_EI(index); - gfar_write(®s->attreli, temp); + gfar_write(®s->attreli, flags); out: unlock_rx_qs(priv); diff --git a/trunk/drivers/net/hamradio/6pack.c b/trunk/drivers/net/hamradio/6pack.c index 689b9bd377a5..fb588301a05d 100644 --- a/trunk/drivers/net/hamradio/6pack.c +++ b/trunk/drivers/net/hamradio/6pack.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #define SIXPACK_VERSION "Revision: 0.3.0" @@ -778,23 +777,6 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file, return err; } -#ifdef CONFIG_COMPAT -static long sixpack_compat_ioctl(struct tty_struct * tty, struct file * file, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case SIOCGIFNAME: - case SIOCGIFENCAP: - case SIOCSIFENCAP: - case SIOCSIFHWADDR: - return sixpack_ioctl(tty, file, cmd, - (unsigned long)compat_ptr(arg)); - } - - return -ENOIOCTLCMD; -} -#endif - static struct tty_ldisc_ops sp_ldisc = { .owner = THIS_MODULE, .magic = TTY_LDISC_MAGIC, @@ -802,9 +784,6 @@ static struct tty_ldisc_ops sp_ldisc = { .open = sixpack_open, .close = sixpack_close, .ioctl = sixpack_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = sixpack_compat_ioctl, -#endif .receive_buf = sixpack_receive_buf, .write_wakeup = sixpack_write_wakeup, }; diff --git a/trunk/drivers/net/hamradio/mkiss.c b/trunk/drivers/net/hamradio/mkiss.c index fc9c57893f8a..db4b7f1603f6 100644 --- a/trunk/drivers/net/hamradio/mkiss.c +++ b/trunk/drivers/net/hamradio/mkiss.c @@ -36,7 +36,6 @@ #include #include #include -#include #include @@ -899,23 +898,6 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file, return err; } -#ifdef CONFIG_COMPAT -static long mkiss_compat_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - switch (arg) { - case SIOCGIFNAME: - case SIOCGIFENCAP: - case SIOCSIFENCAP: - case SIOCSIFHWADDR: - return mkiss_ioctl(tty, file, cmd, - (unsigned long)compat_ptr(arg)); - } - - return -ENOIOCTLCMD; -} -#endif - /* * Handle the 'receiver data ready' interrupt. * This function is called by the 'tty_io' module in the kernel when @@ -990,9 +972,6 @@ static struct tty_ldisc_ops ax_ldisc = { .open = mkiss_open, .close = mkiss_close, .ioctl = mkiss_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = mkiss_compat_ioctl, -#endif .receive_buf = mkiss_receive_buf, .write_wakeup = mkiss_write_wakeup }; diff --git a/trunk/drivers/net/igb/igb.h b/trunk/drivers/net/igb/igb.h index 63abd1c0d75e..3298f5a11dab 100644 --- a/trunk/drivers/net/igb/igb.h +++ b/trunk/drivers/net/igb/igb.h @@ -59,10 +59,10 @@ struct igb_adapter; #define MAX_Q_VECTORS 8 /* Transmit and receive queues */ -#define IGB_MAX_RX_QUEUES (adapter->vfs_allocated_count ? 2 : \ - (hw->mac.type > e1000_82575 ? 8 : 4)) -#define IGB_ABS_MAX_TX_QUEUES 8 -#define IGB_MAX_TX_QUEUES IGB_MAX_RX_QUEUES +#define IGB_MAX_RX_QUEUES (adapter->vfs_allocated_count ? \ + (adapter->vfs_allocated_count > 6 ? 1 : 2) : 4) +#define IGB_MAX_TX_QUEUES IGB_MAX_RX_QUEUES +#define IGB_ABS_MAX_TX_QUEUES 4 #define IGB_MAX_VF_MC_ENTRIES 30 #define IGB_MAX_VF_FUNCTIONS 8 @@ -249,6 +249,10 @@ struct igb_adapter { u16 link_speed; u16 link_duplex; + unsigned int total_tx_bytes; + unsigned int total_tx_packets; + unsigned int total_rx_bytes; + unsigned int total_rx_packets; /* Interrupt Throttle Rate */ u32 rx_itr_setting; u32 tx_itr_setting; @@ -311,7 +315,6 @@ struct igb_adapter { u16 rx_ring_count; unsigned int vfs_allocated_count; struct vf_data_storage *vf_data; - u32 rss_queues; }; #define IGB_FLAG_HAS_MSI (1 << 0) diff --git a/trunk/drivers/net/igb/igb_ethtool.c b/trunk/drivers/net/igb/igb_ethtool.c index c1cde5b44906..90b89a81f669 100644 --- a/trunk/drivers/net/igb/igb_ethtool.c +++ b/trunk/drivers/net/igb/igb_ethtool.c @@ -37,88 +37,77 @@ #include "igb.h" +enum {NETDEV_STATS, IGB_STATS}; + struct igb_stats { char stat_string[ETH_GSTRING_LEN]; + int type; int sizeof_stat; int stat_offset; }; -#define IGB_STAT(_name, _stat) { \ - .stat_string = _name, \ - .sizeof_stat = FIELD_SIZEOF(struct igb_adapter, _stat), \ - .stat_offset = offsetof(struct igb_adapter, _stat) \ -} -static const struct igb_stats igb_gstrings_stats[] = { - IGB_STAT("rx_packets", stats.gprc), - IGB_STAT("tx_packets", stats.gptc), - IGB_STAT("rx_bytes", stats.gorc), - IGB_STAT("tx_bytes", stats.gotc), - IGB_STAT("rx_broadcast", stats.bprc), - IGB_STAT("tx_broadcast", stats.bptc), - IGB_STAT("rx_multicast", stats.mprc), - IGB_STAT("tx_multicast", stats.mptc), - IGB_STAT("multicast", stats.mprc), - IGB_STAT("collisions", stats.colc), - IGB_STAT("rx_crc_errors", stats.crcerrs), - IGB_STAT("rx_no_buffer_count", stats.rnbc), - IGB_STAT("rx_missed_errors", stats.mpc), - IGB_STAT("tx_aborted_errors", stats.ecol), - IGB_STAT("tx_carrier_errors", stats.tncrs), - IGB_STAT("tx_window_errors", stats.latecol), - IGB_STAT("tx_abort_late_coll", stats.latecol), - IGB_STAT("tx_deferred_ok", stats.dc), - IGB_STAT("tx_single_coll_ok", stats.scc), - IGB_STAT("tx_multi_coll_ok", stats.mcc), - IGB_STAT("tx_timeout_count", tx_timeout_count), - IGB_STAT("rx_long_length_errors", stats.roc), - IGB_STAT("rx_short_length_errors", stats.ruc), - IGB_STAT("rx_align_errors", stats.algnerrc), - IGB_STAT("tx_tcp_seg_good", stats.tsctc), - IGB_STAT("tx_tcp_seg_failed", stats.tsctfc), - IGB_STAT("rx_flow_control_xon", stats.xonrxc), - IGB_STAT("rx_flow_control_xoff", stats.xoffrxc), - IGB_STAT("tx_flow_control_xon", stats.xontxc), - IGB_STAT("tx_flow_control_xoff", stats.xofftxc), - IGB_STAT("rx_long_byte_count", stats.gorc), - IGB_STAT("tx_dma_out_of_sync", stats.doosync), - IGB_STAT("tx_smbus", stats.mgptc), - IGB_STAT("rx_smbus", stats.mgprc), - IGB_STAT("dropped_smbus", stats.mgpdc), -}; +#define IGB_STAT(m) IGB_STATS, \ + FIELD_SIZEOF(struct igb_adapter, m), \ + offsetof(struct igb_adapter, m) +#define IGB_NETDEV_STAT(m) NETDEV_STATS, \ + FIELD_SIZEOF(struct net_device, m), \ + offsetof(struct net_device, m) -#define IGB_NETDEV_STAT(_net_stat) { \ - .stat_string = __stringify(_net_stat), \ - .sizeof_stat = FIELD_SIZEOF(struct net_device_stats, _net_stat), \ - .stat_offset = offsetof(struct net_device_stats, _net_stat) \ -} -static const struct igb_stats igb_gstrings_net_stats[] = { - IGB_NETDEV_STAT(rx_errors), - IGB_NETDEV_STAT(tx_errors), - IGB_NETDEV_STAT(tx_dropped), - IGB_NETDEV_STAT(rx_length_errors), - IGB_NETDEV_STAT(rx_over_errors), - IGB_NETDEV_STAT(rx_frame_errors), - IGB_NETDEV_STAT(rx_fifo_errors), - IGB_NETDEV_STAT(tx_fifo_errors), - IGB_NETDEV_STAT(tx_heartbeat_errors) +static const struct igb_stats igb_gstrings_stats[] = { + { "rx_packets", IGB_STAT(stats.gprc) }, + { "tx_packets", IGB_STAT(stats.gptc) }, + { "rx_bytes", IGB_STAT(stats.gorc) }, + { "tx_bytes", IGB_STAT(stats.gotc) }, + { "rx_broadcast", IGB_STAT(stats.bprc) }, + { "tx_broadcast", IGB_STAT(stats.bptc) }, + { "rx_multicast", IGB_STAT(stats.mprc) }, + { "tx_multicast", IGB_STAT(stats.mptc) }, + { "rx_errors", IGB_NETDEV_STAT(stats.rx_errors) }, + { "tx_errors", IGB_NETDEV_STAT(stats.tx_errors) }, + { "tx_dropped", IGB_NETDEV_STAT(stats.tx_dropped) }, + { "multicast", IGB_STAT(stats.mprc) }, + { "collisions", IGB_STAT(stats.colc) }, + { "rx_length_errors", IGB_NETDEV_STAT(stats.rx_length_errors) }, + { "rx_over_errors", IGB_NETDEV_STAT(stats.rx_over_errors) }, + { "rx_crc_errors", IGB_STAT(stats.crcerrs) }, + { "rx_frame_errors", IGB_NETDEV_STAT(stats.rx_frame_errors) }, + { "rx_no_buffer_count", IGB_STAT(stats.rnbc) }, + { "rx_queue_drop_packet_count", IGB_NETDEV_STAT(stats.rx_fifo_errors) }, + { "rx_missed_errors", IGB_STAT(stats.mpc) }, + { "tx_aborted_errors", IGB_STAT(stats.ecol) }, + { "tx_carrier_errors", IGB_STAT(stats.tncrs) }, + { "tx_fifo_errors", IGB_NETDEV_STAT(stats.tx_fifo_errors) }, + { "tx_heartbeat_errors", IGB_NETDEV_STAT(stats.tx_heartbeat_errors) }, + { "tx_window_errors", IGB_STAT(stats.latecol) }, + { "tx_abort_late_coll", IGB_STAT(stats.latecol) }, + { "tx_deferred_ok", IGB_STAT(stats.dc) }, + { "tx_single_coll_ok", IGB_STAT(stats.scc) }, + { "tx_multi_coll_ok", IGB_STAT(stats.mcc) }, + { "tx_timeout_count", IGB_STAT(tx_timeout_count) }, + { "rx_long_length_errors", IGB_STAT(stats.roc) }, + { "rx_short_length_errors", IGB_STAT(stats.ruc) }, + { "rx_align_errors", IGB_STAT(stats.algnerrc) }, + { "tx_tcp_seg_good", IGB_STAT(stats.tsctc) }, + { "tx_tcp_seg_failed", IGB_STAT(stats.tsctfc) }, + { "rx_flow_control_xon", IGB_STAT(stats.xonrxc) }, + { "rx_flow_control_xoff", IGB_STAT(stats.xoffrxc) }, + { "tx_flow_control_xon", IGB_STAT(stats.xontxc) }, + { "tx_flow_control_xoff", IGB_STAT(stats.xofftxc) }, + { "rx_long_byte_count", IGB_STAT(stats.gorc) }, + { "tx_dma_out_of_sync", IGB_STAT(stats.doosync) }, + { "tx_smbus", IGB_STAT(stats.mgptc) }, + { "rx_smbus", IGB_STAT(stats.mgprc) }, + { "dropped_smbus", IGB_STAT(stats.mgpdc) }, }; -#define IGB_GLOBAL_STATS_LEN \ - (sizeof(igb_gstrings_stats) / sizeof(struct igb_stats)) -#define IGB_NETDEV_STATS_LEN \ - (sizeof(igb_gstrings_net_stats) / sizeof(struct igb_stats)) -#define IGB_RX_QUEUE_STATS_LEN \ - (sizeof(struct igb_rx_queue_stats) / sizeof(u64)) -#define IGB_TX_QUEUE_STATS_LEN \ - (sizeof(struct igb_tx_queue_stats) / sizeof(u64)) #define IGB_QUEUE_STATS_LEN \ ((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues * \ - IGB_RX_QUEUE_STATS_LEN) + \ + (sizeof(struct igb_rx_queue_stats) / sizeof(u64))) + \ (((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues * \ - IGB_TX_QUEUE_STATS_LEN)) -#define IGB_STATS_LEN \ - (IGB_GLOBAL_STATS_LEN + IGB_NETDEV_STATS_LEN + IGB_QUEUE_STATS_LEN) - + (sizeof(struct igb_tx_queue_stats) / sizeof(u64)))) +#define IGB_GLOBAL_STATS_LEN \ + (sizeof(igb_gstrings_stats) / sizeof(struct igb_stats)) +#define IGB_STATS_LEN (IGB_GLOBAL_STATS_LEN + IGB_QUEUE_STATS_LEN) static const char igb_gstrings_test[][ETH_GSTRING_LEN] = { "Register test (offline)", "Eeprom test (offline)", "Interrupt test (offline)", "Loopback test (offline)", @@ -746,17 +735,17 @@ static int igb_set_ringparam(struct net_device *netdev, struct igb_adapter *adapter = netdev_priv(netdev); struct igb_ring *temp_ring; int i, err = 0; - u16 new_rx_count, new_tx_count; + u32 new_rx_count, new_tx_count; if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) return -EINVAL; - new_rx_count = min_t(u32, ring->rx_pending, IGB_MAX_RXD); - new_rx_count = max_t(u16, new_rx_count, IGB_MIN_RXD); + new_rx_count = min(ring->rx_pending, (u32)IGB_MAX_RXD); + new_rx_count = max(new_rx_count, (u32)IGB_MIN_RXD); new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE); - new_tx_count = min_t(u32, ring->tx_pending, IGB_MAX_TXD); - new_tx_count = max_t(u16, new_tx_count, IGB_MIN_TXD); + new_tx_count = min(ring->tx_pending, (u32)IGB_MAX_TXD); + new_tx_count = max(new_tx_count, (u32)IGB_MIN_TXD); new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE); if ((new_tx_count == adapter->tx_ring_count) && @@ -1933,32 +1922,43 @@ static void igb_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data) { struct igb_adapter *adapter = netdev_priv(netdev); - struct net_device_stats *net_stats = &netdev->stats; u64 *queue_stat; - int i, j, k; - char *p; + int stat_count_tx = sizeof(struct igb_tx_queue_stats) / sizeof(u64); + int stat_count_rx = sizeof(struct igb_rx_queue_stats) / sizeof(u64); + int j; + int i; + char *p = NULL; igb_update_stats(adapter); for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { - p = (char *)adapter + igb_gstrings_stats[i].stat_offset; + switch (igb_gstrings_stats[i].type) { + case NETDEV_STATS: + p = (char *) netdev + + igb_gstrings_stats[i].stat_offset; + break; + case IGB_STATS: + p = (char *) adapter + + igb_gstrings_stats[i].stat_offset; + break; + } + data[i] = (igb_gstrings_stats[i].sizeof_stat == sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } - for (j = 0; j < IGB_NETDEV_STATS_LEN; j++, i++) { - p = (char *)net_stats + igb_gstrings_net_stats[j].stat_offset; - data[i] = (igb_gstrings_net_stats[j].sizeof_stat == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } for (j = 0; j < adapter->num_tx_queues; j++) { + int k; queue_stat = (u64 *)&adapter->tx_ring[j].tx_stats; - for (k = 0; k < IGB_TX_QUEUE_STATS_LEN; k++, i++) - data[i] = queue_stat[k]; + for (k = 0; k < stat_count_tx; k++) + data[i + k] = queue_stat[k]; + i += k; } for (j = 0; j < adapter->num_rx_queues; j++) { + int k; queue_stat = (u64 *)&adapter->rx_ring[j].rx_stats; - for (k = 0; k < IGB_RX_QUEUE_STATS_LEN; k++, i++) - data[i] = queue_stat[k]; + for (k = 0; k < stat_count_rx; k++) + data[i + k] = queue_stat[k]; + i += k; } } @@ -1979,11 +1979,6 @@ static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data) ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } - for (i = 0; i < IGB_NETDEV_STATS_LEN; i++) { - memcpy(p, igb_gstrings_net_stats[i].stat_string, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - } for (i = 0; i < adapter->num_tx_queues; i++) { sprintf(p, "tx_queue_%u_packets", i); p += ETH_GSTRING_LEN; diff --git a/trunk/drivers/net/igb/igb_main.c b/trunk/drivers/net/igb/igb_main.c index 0cab5e2b0894..b044c985df0b 100644 --- a/trunk/drivers/net/igb/igb_main.c +++ b/trunk/drivers/net/igb/igb_main.c @@ -296,10 +296,10 @@ static void igb_cache_ring_register(struct igb_adapter *adapter) * and continue consuming queues in the same sequence */ if (adapter->vfs_allocated_count) { - for (; i < adapter->rss_queues; i++) + for (; i < adapter->num_rx_queues; i++) adapter->rx_ring[i].reg_idx = rbase_offset + Q_IDX_82576(i); - for (; j < adapter->rss_queues; j++) + for (; j < adapter->num_tx_queues; j++) adapter->tx_ring[j].reg_idx = rbase_offset + Q_IDX_82576(j); } @@ -618,15 +618,14 @@ static void igb_set_interrupt_capability(struct igb_adapter *adapter) int numvecs, i; /* Number of supported queues. */ - adapter->num_rx_queues = adapter->rss_queues; - adapter->num_tx_queues = adapter->rss_queues; + adapter->num_rx_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus()); + adapter->num_tx_queues = min_t(u32, IGB_MAX_TX_QUEUES, num_online_cpus()); /* start with one vector for every rx queue */ numvecs = adapter->num_rx_queues; /* if tx handler is seperate add 1 for every tx queue */ - if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS)) - numvecs += adapter->num_tx_queues; + numvecs += adapter->num_tx_queues; /* store the number of vectors reserved for queues */ adapter->num_q_vectors = numvecs; @@ -667,7 +666,6 @@ static void igb_set_interrupt_capability(struct igb_adapter *adapter) } #endif adapter->vfs_allocated_count = 0; - adapter->rss_queues = 1; adapter->flags |= IGB_FLAG_QUEUE_PAIRS; adapter->num_rx_queues = 1; adapter->num_tx_queues = 1; @@ -1568,6 +1566,56 @@ static int __devinit igb_probe(struct pci_dev *pdev, } #endif + switch (hw->mac.type) { + case e1000_82576: + /* + * Initialize hardware timer: we keep it running just in case + * that some program needs it later on. + */ + memset(&adapter->cycles, 0, sizeof(adapter->cycles)); + adapter->cycles.read = igb_read_clock; + adapter->cycles.mask = CLOCKSOURCE_MASK(64); + adapter->cycles.mult = 1; + /** + * Scale the NIC clock cycle by a large factor so that + * relatively small clock corrections can be added or + * substracted at each clock tick. The drawbacks of a large + * factor are a) that the clock register overflows more quickly + * (not such a big deal) and b) that the increment per tick has + * to fit into 24 bits. As a result we need to use a shift of + * 19 so we can fit a value of 16 into the TIMINCA register. + */ + adapter->cycles.shift = IGB_82576_TSYNC_SHIFT; + wr32(E1000_TIMINCA, + (1 << E1000_TIMINCA_16NS_SHIFT) | + (16 << IGB_82576_TSYNC_SHIFT)); + + /* Set registers so that rollover occurs soon to test this. */ + wr32(E1000_SYSTIML, 0x00000000); + wr32(E1000_SYSTIMH, 0xFF800000); + wrfl(); + + timecounter_init(&adapter->clock, + &adapter->cycles, + ktime_to_ns(ktime_get_real())); + /* + * Synchronize our NIC clock against system wall clock. NIC + * time stamp reading requires ~3us per sample, each sample + * was pretty stable even under load => only require 10 + * samples for each offset comparison. + */ + memset(&adapter->compare, 0, sizeof(adapter->compare)); + adapter->compare.source = &adapter->clock; + adapter->compare.target = ktime_get_real; + adapter->compare.num_samples = 10; + timecompare_update(&adapter->compare, 0); + break; + case e1000_82575: + /* 82575 does not support timesync */ + default: + break; + } + dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n"); /* print bus type/speed/width info */ dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n", @@ -1733,70 +1781,6 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter) #endif /* CONFIG_PCI_IOV */ } - -/** - * igb_init_hw_timer - Initialize hardware timer used with IEEE 1588 timestamp - * @adapter: board private structure to initialize - * - * igb_init_hw_timer initializes the function pointer and values for the hw - * timer found in hardware. - **/ -static void igb_init_hw_timer(struct igb_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - switch (hw->mac.type) { - case e1000_82576: - /* - * Initialize hardware timer: we keep it running just in case - * that some program needs it later on. - */ - memset(&adapter->cycles, 0, sizeof(adapter->cycles)); - adapter->cycles.read = igb_read_clock; - adapter->cycles.mask = CLOCKSOURCE_MASK(64); - adapter->cycles.mult = 1; - /** - * Scale the NIC clock cycle by a large factor so that - * relatively small clock corrections can be added or - * substracted at each clock tick. The drawbacks of a large - * factor are a) that the clock register overflows more quickly - * (not such a big deal) and b) that the increment per tick has - * to fit into 24 bits. As a result we need to use a shift of - * 19 so we can fit a value of 16 into the TIMINCA register. - */ - adapter->cycles.shift = IGB_82576_TSYNC_SHIFT; - wr32(E1000_TIMINCA, - (1 << E1000_TIMINCA_16NS_SHIFT) | - (16 << IGB_82576_TSYNC_SHIFT)); - - /* Set registers so that rollover occurs soon to test this. */ - wr32(E1000_SYSTIML, 0x00000000); - wr32(E1000_SYSTIMH, 0xFF800000); - wrfl(); - - timecounter_init(&adapter->clock, - &adapter->cycles, - ktime_to_ns(ktime_get_real())); - /* - * Synchronize our NIC clock against system wall clock. NIC - * time stamp reading requires ~3us per sample, each sample - * was pretty stable even under load => only require 10 - * samples for each offset comparison. - */ - memset(&adapter->compare, 0, sizeof(adapter->compare)); - adapter->compare.source = &adapter->clock; - adapter->compare.target = ktime_get_real; - adapter->compare.num_samples = 10; - timecompare_update(&adapter->compare, 0); - break; - case e1000_82575: - /* 82575 does not support timesync */ - default: - break; - } - -} - /** * igb_sw_init - Initialize general software structures (struct igb_adapter) * @adapter: board private structure to initialize @@ -1826,24 +1810,12 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) adapter->vfs_allocated_count = max_vfs; #endif /* CONFIG_PCI_IOV */ - adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus()); - - /* - * if rss_queues > 4 or vfs are going to be allocated with rss_queues - * then we should combine the queues into a queue pair in order to - * conserve interrupts due to limited supply - */ - if ((adapter->rss_queues > 4) || - ((adapter->rss_queues > 1) && (adapter->vfs_allocated_count > 6))) - adapter->flags |= IGB_FLAG_QUEUE_PAIRS; - /* This call may decrease the number of queues */ if (igb_init_interrupt_scheme(adapter)) { dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); return -ENOMEM; } - igb_init_hw_timer(adapter); igb_probe_vfs(adapter); /* Explicitly disable IRQ since the NIC can be in any state. */ @@ -2028,7 +2000,7 @@ static int igb_setup_all_tx_resources(struct igb_adapter *adapter) } } - for (i = 0; i < IGB_ABS_MAX_TX_QUEUES; i++) { + for (i = 0; i < IGB_MAX_TX_QUEUES; i++) { int r_idx = i % adapter->num_tx_queues; adapter->multi_tx_table[i] = &adapter->tx_ring[r_idx]; } @@ -2212,7 +2184,7 @@ static void igb_setup_mrqc(struct igb_adapter *adapter) array_wr32(E1000_RSSRK(0), j, rsskey); } - num_rx_queues = adapter->rss_queues; + num_rx_queues = adapter->num_rx_queues; if (adapter->vfs_allocated_count) { /* 82575 and 82576 supports 2 RSS queues for VMDq */ @@ -2268,7 +2240,7 @@ static void igb_setup_mrqc(struct igb_adapter *adapter) E1000_VT_CTL_DEFAULT_POOL_SHIFT; wr32(E1000_VT_CTL, vtctl); } - if (adapter->rss_queues > 1) + if (adapter->num_rx_queues > 1) mrqc = E1000_MRQC_ENABLE_VMDQ_RSS_2Q; else mrqc = E1000_MRQC_ENABLE_VMDQ; @@ -2398,7 +2370,7 @@ static inline void igb_set_vmolr(struct igb_adapter *adapter, int vfn) /* clear all bits that might not be set */ vmolr &= ~(E1000_VMOLR_BAM | E1000_VMOLR_RSSE); - if (adapter->rss_queues > 1 && vfn == adapter->vfs_allocated_count) + if (adapter->num_rx_queues > 1 && vfn == adapter->vfs_allocated_count) vmolr |= E1000_VMOLR_RSSE; /* enable RSS */ /* * for VMDq only allow the VFs and pool 0 to accept broadcast and @@ -2943,6 +2915,7 @@ static void igb_watchdog_task(struct work_struct *work) watchdog_task); struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; + struct igb_ring *tx_ring = adapter->tx_ring; u32 link; int i; @@ -3012,25 +2985,23 @@ static void igb_watchdog_task(struct work_struct *work) igb_update_stats(adapter); igb_update_adaptive(hw); - for (i = 0; i < adapter->num_tx_queues; i++) { - struct igb_ring *tx_ring = &adapter->tx_ring[i]; - if (!netif_carrier_ok(netdev)) { + if (!netif_carrier_ok(netdev)) { + if (igb_desc_unused(tx_ring) + 1 < tx_ring->count) { /* We've lost link, so the controller stops DMA, * but we've got queued Tx work that's never going * to get done, so reset controller to flush Tx. * (Do the reset outside of interrupt context). */ - if (igb_desc_unused(tx_ring) + 1 < tx_ring->count) { - adapter->tx_timeout_count++; - schedule_work(&adapter->reset_task); - /* return immediately since reset is imminent */ - return; - } + adapter->tx_timeout_count++; + schedule_work(&adapter->reset_task); + /* return immediately since reset is imminent */ + return; } - - /* Force detection of hung controller every watchdog period */ - tx_ring->detect_tx_hung = true; } + /* Force detection of hung controller every watchdog period */ + for (i = 0; i < adapter->num_tx_queues; i++) + adapter->tx_ring[i].detect_tx_hung = true; + /* Cause software interrupt to ensure rx ring is cleaned */ if (adapter->msix_entries) { u32 eics = 0; @@ -3790,7 +3761,7 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu) void igb_update_stats(struct igb_adapter *adapter) { - struct net_device_stats *net_stats = igb_get_stats(adapter->netdev); + struct net_device *netdev = adapter->netdev; struct e1000_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; u32 rnbc; @@ -3814,13 +3785,13 @@ void igb_update_stats(struct igb_adapter *adapter) for (i = 0; i < adapter->num_rx_queues; i++) { u32 rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0x0FFF; adapter->rx_ring[i].rx_stats.drops += rqdpc_tmp; - net_stats->rx_fifo_errors += rqdpc_tmp; + netdev->stats.rx_fifo_errors += rqdpc_tmp; bytes += adapter->rx_ring[i].rx_stats.bytes; packets += adapter->rx_ring[i].rx_stats.packets; } - net_stats->rx_bytes = bytes; - net_stats->rx_packets = packets; + netdev->stats.rx_bytes = bytes; + netdev->stats.rx_packets = packets; bytes = 0; packets = 0; @@ -3828,8 +3799,8 @@ void igb_update_stats(struct igb_adapter *adapter) bytes += adapter->tx_ring[i].tx_stats.bytes; packets += adapter->tx_ring[i].tx_stats.packets; } - net_stats->tx_bytes = bytes; - net_stats->tx_packets = packets; + netdev->stats.tx_bytes = bytes; + netdev->stats.tx_packets = packets; /* read stats registers */ adapter->stats.crcerrs += rd32(E1000_CRCERRS); @@ -3866,7 +3837,7 @@ void igb_update_stats(struct igb_adapter *adapter) rd32(E1000_GOTCH); /* clear GOTCL */ rnbc = rd32(E1000_RNBC); adapter->stats.rnbc += rnbc; - net_stats->rx_fifo_errors += rnbc; + netdev->stats.rx_fifo_errors += rnbc; adapter->stats.ruc += rd32(E1000_RUC); adapter->stats.rfc += rd32(E1000_RFC); adapter->stats.rjc += rd32(E1000_RJC); @@ -3907,29 +3878,29 @@ void igb_update_stats(struct igb_adapter *adapter) adapter->stats.icrxdmtc += rd32(E1000_ICRXDMTC); /* Fill out the OS statistics structure */ - net_stats->multicast = adapter->stats.mprc; - net_stats->collisions = adapter->stats.colc; + netdev->stats.multicast = adapter->stats.mprc; + netdev->stats.collisions = adapter->stats.colc; /* Rx Errors */ /* RLEC on some newer hardware can be incorrect so build * our own version based on RUC and ROC */ - net_stats->rx_errors = adapter->stats.rxerrc + + netdev->stats.rx_errors = adapter->stats.rxerrc + adapter->stats.crcerrs + adapter->stats.algnerrc + adapter->stats.ruc + adapter->stats.roc + adapter->stats.cexterr; - net_stats->rx_length_errors = adapter->stats.ruc + - adapter->stats.roc; - net_stats->rx_crc_errors = adapter->stats.crcerrs; - net_stats->rx_frame_errors = adapter->stats.algnerrc; - net_stats->rx_missed_errors = adapter->stats.mpc; + netdev->stats.rx_length_errors = adapter->stats.ruc + + adapter->stats.roc; + netdev->stats.rx_crc_errors = adapter->stats.crcerrs; + netdev->stats.rx_frame_errors = adapter->stats.algnerrc; + netdev->stats.rx_missed_errors = adapter->stats.mpc; /* Tx Errors */ - net_stats->tx_errors = adapter->stats.ecol + - adapter->stats.latecol; - net_stats->tx_aborted_errors = adapter->stats.ecol; - net_stats->tx_window_errors = adapter->stats.latecol; - net_stats->tx_carrier_errors = adapter->stats.tncrs; + netdev->stats.tx_errors = adapter->stats.ecol + + adapter->stats.latecol; + netdev->stats.tx_aborted_errors = adapter->stats.ecol; + netdev->stats.tx_window_errors = adapter->stats.latecol; + netdev->stats.tx_carrier_errors = adapter->stats.tncrs; /* Tx Dropped needs to be maintained elsewhere */ @@ -4952,7 +4923,6 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector, struct sk_buff *skb; bool cleaned = false; int cleaned_count = 0; - int current_node = numa_node_id(); unsigned int total_bytes = 0, total_packets = 0; unsigned int i; u32 staterr; @@ -5007,8 +4977,7 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector, buffer_info->page_offset, length); - if ((page_count(buffer_info->page) != 1) || - (page_to_nid(buffer_info->page) != current_node)) + if (page_count(buffer_info->page) != 1) buffer_info->page = NULL; else get_page(buffer_info->page); diff --git a/trunk/drivers/net/ixgbe/ixgbe_main.c b/trunk/drivers/net/ixgbe/ixgbe_main.c index 884152d1085e..45c5faf0824a 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ixgbe/ixgbe_main.c @@ -44,7 +44,6 @@ #include "ixgbe.h" #include "ixgbe_common.h" -#include "ixgbe_dcb_82599.h" char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = @@ -229,56 +228,6 @@ static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter, /* tx_buffer_info must be completely set up in the transmit path */ } -/** - * ixgbe_tx_is_paused - check if the tx ring is paused - * @adapter: the ixgbe adapter - * @tx_ring: the corresponding tx_ring - * - * If not in DCB mode, checks TFCS.TXOFF, otherwise, find out the - * corresponding TC of this tx_ring when checking TFCS. - * - * Returns : true if paused - */ -static inline bool ixgbe_tx_is_paused(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring) -{ - int tc; - u32 txoff = IXGBE_TFCS_TXOFF; - -#ifdef CONFIG_IXGBE_DCB - if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - int reg_idx = tx_ring->reg_idx; - int dcb_i = adapter->ring_feature[RING_F_DCB].indices; - - if (adapter->hw.mac.type == ixgbe_mac_82598EB) { - tc = reg_idx >> 2; - txoff = IXGBE_TFCS_TXOFF0; - } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - tc = 0; - txoff = IXGBE_TFCS_TXOFF; - if (dcb_i == 8) { - /* TC0, TC1 */ - tc = reg_idx >> 5; - if (tc == 2) /* TC2, TC3 */ - tc += (reg_idx - 64) >> 4; - else if (tc == 3) /* TC4, TC5, TC6, TC7 */ - tc += 1 + ((reg_idx - 96) >> 3); - } else if (dcb_i == 4) { - /* TC0, TC1 */ - tc = reg_idx >> 6; - if (tc == 1) { - tc += (reg_idx - 64) >> 5; - if (tc == 2) /* TC2, TC3 */ - tc += (reg_idx - 96) >> 4; - } - } - } - txoff <<= tc; - } -#endif - return IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & txoff; -} - static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring, unsigned int eop) @@ -290,7 +239,7 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, adapter->detect_tx_hung = false; if (tx_ring->tx_buffer_info[eop].time_stamp && time_after(jiffies, tx_ring->tx_buffer_info[eop].time_stamp + HZ) && - !ixgbe_tx_is_paused(adapter, tx_ring)) { + !(IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF)) { /* detected Tx unit hang */ union ixgbe_adv_tx_desc *tx_desc; tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); @@ -465,23 +414,19 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter, u32 txctrl; int cpu = get_cpu(); int q = tx_ring - adapter->tx_ring; - struct ixgbe_hw *hw = &adapter->hw; if (tx_ring->cpu != cpu) { + txctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q)); if (adapter->hw.mac.type == ixgbe_mac_82598EB) { - txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(q)); txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK; txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); - txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; - IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(q), txctrl); } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(q)); txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK_82599; txctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) << - IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599); - txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; - IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(q), txctrl); + IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599); } + txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q), txctrl); tx_ring->cpu = cpu; } put_cpu(); @@ -1204,7 +1149,6 @@ static void ixgbe_check_lsc(struct ixgbe_adapter *adapter) adapter->link_check_timeout = jiffies; if (!test_bit(__IXGBE_DOWN, &adapter->state)) { IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); - IXGBE_WRITE_FLUSH(hw); schedule_work(&adapter->watchdog_task); } } @@ -1340,6 +1284,8 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data) if (!q_vector->rxr_count) return IRQ_HANDLED; + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + rx_ring = &(adapter->rx_ring[r_idx]); /* disable interrupts on this vector only */ ixgbe_irq_disable_queues(adapter, ((u64)1 << q_vector->v_idx)); napi_schedule(&q_vector->napi); @@ -1962,25 +1908,11 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) break; } } - if (hw->mac.type == ixgbe_mac_82599EB) { - u32 rttdcs; - - /* disable the arbiter while setting MTQC */ - rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); - rttdcs |= IXGBE_RTTDCS_ARBDIS; - IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); - /* We enable 8 traffic classes, DCB only */ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) IXGBE_WRITE_REG(hw, IXGBE_MTQC, (IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ)); - else - IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB); - - /* re-eable the arbiter */ - rttdcs &= ~IXGBE_RTTDCS_ARBDIS; - IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); } } @@ -2534,10 +2466,7 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter) ixgbe_restore_vlan(adapter); #ifdef CONFIG_IXGBE_DCB if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - if (hw->mac.type == ixgbe_mac_82598EB) - netif_set_gso_max_size(netdev, 32768); - else - netif_set_gso_max_size(netdev, 65536); + netif_set_gso_max_size(netdev, 32768); ixgbe_configure_dcb(adapter); } else { netif_set_gso_max_size(netdev, 65536); @@ -3626,10 +3555,10 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter) * It's easy to be greedy for MSI-X vectors, but it really * doesn't do us much good if we have a lot more vectors * than CPU's. So let's be conservative and only ask for - * (roughly) the same number of vectors as there are CPU's. + * (roughly) twice the number of vectors as there are CPU's. */ v_budget = min(adapter->num_rx_queues + adapter->num_tx_queues, - (int)num_online_cpus()) + NON_Q_VECTORS; + (int)(num_online_cpus() * 2)) + NON_Q_VECTORS; /* * At the same time, hardware can only support a maximum of diff --git a/trunk/drivers/net/macsonic.c b/trunk/drivers/net/macsonic.c index b3d7d8d77f46..61eabcac734c 100644 --- a/trunk/drivers/net/macsonic.c +++ b/trunk/drivers/net/macsonic.c @@ -223,73 +223,69 @@ static int __devinit macsonic_init(struct net_device *dev) return 0; } -#define INVALID_MAC(mac) (memcmp(mac, "\x08\x00\x07", 3) && \ - memcmp(mac, "\x00\xA0\x40", 3) && \ - memcmp(mac, "\x00\x80\x19", 3) && \ - memcmp(mac, "\x00\x05\x02", 3)) - -static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev) +static int __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev) { struct sonic_local *lp = netdev_priv(dev); const int prom_addr = ONBOARD_SONIC_PROM_BASE; - unsigned short val; - - /* - * On NuBus boards we can sometimes look in the ROM resources. - * No such luck for comm-slot/onboard. - * On the PowerBook 520, the PROM base address is a mystery. - */ - if (hwreg_present((void *)prom_addr)) { - int i; + int i; - for (i = 0; i < 6; i++) - dev->dev_addr[i] = SONIC_READ_PROM(i); - if (!INVALID_MAC(dev->dev_addr)) - return; + /* On NuBus boards we can sometimes look in the ROM resources. + No such luck for comm-slot/onboard. */ + for(i = 0; i < 6; i++) + dev->dev_addr[i] = SONIC_READ_PROM(i); - /* - * Most of the time, the address is bit-reversed. The NetBSD - * source has a rather long and detailed historical account of - * why this is so. - */ + /* Most of the time, the address is bit-reversed. The NetBSD + source has a rather long and detailed historical account of + why this is so. */ + if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) && + memcmp(dev->dev_addr, "\x00\xA0\x40", 3) && + memcmp(dev->dev_addr, "\x00\x80\x19", 3) && + memcmp(dev->dev_addr, "\x00\x05\x02", 3)) bit_reverse_addr(dev->dev_addr); - if (!INVALID_MAC(dev->dev_addr)) - return; - + else + return 0; + + /* If we still have what seems to be a bogus address, we'll + look in the CAM. The top entry should be ours. */ + /* Danger! This only works if MacOS has already initialized + the card... */ + if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) && + memcmp(dev->dev_addr, "\x00\xA0\x40", 3) && + memcmp(dev->dev_addr, "\x00\x80\x19", 3) && + memcmp(dev->dev_addr, "\x00\x05\x02", 3)) + { + unsigned short val; + + printk(KERN_INFO "macsonic: PROM seems to be wrong, trying CAM entry 15\n"); + + SONIC_WRITE(SONIC_CMD, SONIC_CR_RST); + SONIC_WRITE(SONIC_CEP, 15); + + val = SONIC_READ(SONIC_CAP2); + dev->dev_addr[5] = val >> 8; + dev->dev_addr[4] = val & 0xff; + val = SONIC_READ(SONIC_CAP1); + dev->dev_addr[3] = val >> 8; + dev->dev_addr[2] = val & 0xff; + val = SONIC_READ(SONIC_CAP0); + dev->dev_addr[1] = val >> 8; + dev->dev_addr[0] = val & 0xff; + + printk(KERN_INFO "HW Address from CAM 15: %pM\n", + dev->dev_addr); + } else return 0; + + if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) && + memcmp(dev->dev_addr, "\x00\xA0\x40", 3) && + memcmp(dev->dev_addr, "\x00\x80\x19", 3) && + memcmp(dev->dev_addr, "\x00\x05\x02", 3)) + { /* - * If we still have what seems to be a bogus address, we'll - * look in the CAM. The top entry should be ours. + * Still nonsense ... messed up someplace! */ - printk(KERN_WARNING "macsonic: MAC address in PROM seems " - "to be invalid, trying CAM\n"); - } else { - printk(KERN_WARNING "macsonic: cannot read MAC address from " - "PROM, trying CAM\n"); - } - - /* This only works if MacOS has already initialized the card. */ - - SONIC_WRITE(SONIC_CMD, SONIC_CR_RST); - SONIC_WRITE(SONIC_CEP, 15); - - val = SONIC_READ(SONIC_CAP2); - dev->dev_addr[5] = val >> 8; - dev->dev_addr[4] = val & 0xff; - val = SONIC_READ(SONIC_CAP1); - dev->dev_addr[3] = val >> 8; - dev->dev_addr[2] = val & 0xff; - val = SONIC_READ(SONIC_CAP0); - dev->dev_addr[1] = val >> 8; - dev->dev_addr[0] = val & 0xff; - - if (!INVALID_MAC(dev->dev_addr)) - return; - - /* Still nonsense ... messed up someplace! */ - - printk(KERN_WARNING "macsonic: MAC address in CAM entry 15 " - "seems invalid, will use a random MAC\n"); - random_ether_addr(dev->dev_addr); + printk(KERN_ERR "macsonic: ERROR (INVALID MAC)\n"); + return -EIO; + } else return 0; } static int __devinit mac_onboard_sonic_probe(struct net_device *dev) @@ -406,7 +402,8 @@ static int __devinit mac_onboard_sonic_probe(struct net_device *dev) SONIC_WRITE(SONIC_ISR, 0x7fff); /* Now look for the MAC address. */ - mac_onboard_sonic_ethernet_addr(dev); + if (mac_onboard_sonic_ethernet_addr(dev) != 0) + return -ENODEV; /* Shared init code */ return macsonic_init(dev); diff --git a/trunk/drivers/net/macvlan.c b/trunk/drivers/net/macvlan.c index 271aa7e1d033..20b7707f38ef 100644 --- a/trunk/drivers/net/macvlan.c +++ b/trunk/drivers/net/macvlan.c @@ -202,7 +202,7 @@ static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, } else txq->tx_dropped++; - return ret; + return NETDEV_TX_OK; } static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev, @@ -504,7 +504,7 @@ static int macvlan_get_tx_queues(struct net *net, return 0; } -static int macvlan_newlink(struct net *src_net, struct net_device *dev, +static int macvlan_newlink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { struct macvlan_dev *vlan = netdev_priv(dev); @@ -515,7 +515,7 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev, if (!tb[IFLA_LINK]) return -EINVAL; - lowerdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); + lowerdev = __dev_get_by_index(dev_net(dev), nla_get_u32(tb[IFLA_LINK])); if (lowerdev == NULL) return -ENODEV; diff --git a/trunk/drivers/net/myri10ge/myri10ge.c b/trunk/drivers/net/myri10ge/myri10ge.c index 85e1b6a3ac1b..5319db9901d8 100644 --- a/trunk/drivers/net/myri10ge/myri10ge.c +++ b/trunk/drivers/net/myri10ge/myri10ge.c @@ -263,10 +263,6 @@ static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat"; static char *myri10ge_fw_aligned = "myri10ge_eth_z8e.dat"; static char *myri10ge_fw_rss_unaligned = "myri10ge_rss_ethp_z8e.dat"; static char *myri10ge_fw_rss_aligned = "myri10ge_rss_eth_z8e.dat"; -MODULE_FIRMWARE("myri10ge_ethp_z8e.dat"); -MODULE_FIRMWARE("myri10ge_eth_z8e.dat"); -MODULE_FIRMWARE("myri10ge_rss_ethp_z8e.dat"); -MODULE_FIRMWARE("myri10ge_rss_eth_z8e.dat"); static char *myri10ge_fw_name = NULL; module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); diff --git a/trunk/drivers/net/netx-eth.c b/trunk/drivers/net/netx-eth.c index a0d65f592a12..9f4235466d59 100644 --- a/trunk/drivers/net/netx-eth.c +++ b/trunk/drivers/net/netx-eth.c @@ -510,6 +510,3 @@ module_exit(netx_eth_cleanup); MODULE_AUTHOR("Sascha Hauer, Pengutronix"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" CARDNAME); -MODULE_FIRMWARE("xc0.bin"); -MODULE_FIRMWARE("xc1.bin"); -MODULE_FIRMWARE("xc2.bin"); diff --git a/trunk/drivers/net/niu.c b/trunk/drivers/net/niu.c index 8ce58c4c7dd3..5506f870037f 100644 --- a/trunk/drivers/net/niu.c +++ b/trunk/drivers/net/niu.c @@ -45,6 +45,10 @@ MODULE_DESCRIPTION("NIU ethernet driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); +#ifndef DMA_44BIT_MASK +#define DMA_44BIT_MASK 0x00000fffffffffffULL +#endif + #ifndef readq static u64 readq(void __iomem *reg) { @@ -8143,7 +8147,7 @@ static void __devinit niu_vpd_parse_version(struct niu *np) int i; for (i = 0; i < len - 5; i++) { - if (!strncmp(s + i, "FCode ", 6)) + if (!strncmp(s + i, "FCode ", 5)) break; } if (i >= len - 5) @@ -9914,7 +9918,7 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev, PCI_EXP_DEVCTL_RELAX_EN); pci_write_config_word(pdev, pos + PCI_EXP_DEVCTL, val16); - dma_mask = DMA_BIT_MASK(44); + dma_mask = DMA_44BIT_MASK; err = pci_set_dma_mask(pdev, dma_mask); if (!err) { dev->features |= NETIF_F_HIGHDMA; diff --git a/trunk/drivers/net/pcmcia/pcnet_cs.c b/trunk/drivers/net/pcmcia/pcnet_cs.c index 469684474b72..bd3447f04902 100644 --- a/trunk/drivers/net/pcmcia/pcnet_cs.c +++ b/trunk/drivers/net/pcmcia/pcnet_cs.c @@ -1760,7 +1760,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_CIS_MANF_CARD(0xc00f, 0x0002, "cis/LA-PCM.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "PE520.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "cis/PE-200.cis"), + PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "cis/tamarack.cis"), PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b), PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0", @@ -1768,13 +1768,6 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_NULL }; MODULE_DEVICE_TABLE(pcmcia, pcnet_ids); -MODULE_FIRMWARE("cis/PCMLM28.cis"); -MODULE_FIRMWARE("cis/DP83903.cis"); -MODULE_FIRMWARE("cis/LA-PCM.cis"); -MODULE_FIRMWARE("PE520.cis"); -MODULE_FIRMWARE("cis/NE2K.cis"); -MODULE_FIRMWARE("cis/PE-200.cis"); -MODULE_FIRMWARE("cis/tamarack.cis"); static struct pcmcia_driver pcnet_driver = { .drv = { diff --git a/trunk/drivers/net/pppox.c b/trunk/drivers/net/pppox.c index ac806b27c658..c14ee24c05a8 100644 --- a/trunk/drivers/net/pppox.c +++ b/trunk/drivers/net/pppox.c @@ -104,8 +104,7 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) EXPORT_SYMBOL(pppox_ioctl); -static int pppox_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int pppox_create(struct net *net, struct socket *sock, int protocol) { int rc = -EPROTOTYPE; diff --git a/trunk/drivers/net/qlge/qlge.h b/trunk/drivers/net/qlge/qlge.h index 862c1aaf3860..1f59f054452d 100644 --- a/trunk/drivers/net/qlge/qlge.h +++ b/trunk/drivers/net/qlge/qlge.h @@ -16,7 +16,7 @@ */ #define DRV_NAME "qlge" #define DRV_STRING "QLogic 10 Gigabit PCI-E Ethernet Driver " -#define DRV_VERSION "v1.00.00.23.00.00-01" +#define DRV_VERSION "v1.00.00-b3" #define PFX "qlge: " #define QPRINTK(qdev, nlevel, klevel, fmt, args...) \ diff --git a/trunk/drivers/net/qlge/qlge_main.c b/trunk/drivers/net/qlge/qlge_main.c index e2ee47d9bca5..0de596ad8a7e 100644 --- a/trunk/drivers/net/qlge/qlge_main.c +++ b/trunk/drivers/net/qlge/qlge_main.c @@ -69,9 +69,9 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); #define MSIX_IRQ 0 #define MSI_IRQ 1 #define LEG_IRQ 2 -static int qlge_irq_type = MSIX_IRQ; -module_param(qlge_irq_type, int, MSIX_IRQ); -MODULE_PARM_DESC(qlge_irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy."); +static int irq_type = MSIX_IRQ; +module_param(irq_type, int, MSIX_IRQ); +MODULE_PARM_DESC(irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy."); static struct pci_device_id qlge_pci_tbl[] __devinitdata = { {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)}, @@ -2870,7 +2870,7 @@ static void ql_enable_msix(struct ql_adapter *qdev) int i, err; /* Get the MSIX vectors. */ - if (qlge_irq_type == MSIX_IRQ) { + if (irq_type == MSIX_IRQ) { /* Try to alloc space for the msix struct, * if it fails then go to MSI/legacy. */ @@ -2878,7 +2878,7 @@ static void ql_enable_msix(struct ql_adapter *qdev) sizeof(struct msix_entry), GFP_KERNEL); if (!qdev->msi_x_entry) { - qlge_irq_type = MSI_IRQ; + irq_type = MSI_IRQ; goto msi; } @@ -2901,7 +2901,7 @@ static void ql_enable_msix(struct ql_adapter *qdev) QPRINTK(qdev, IFUP, WARNING, "MSI-X Enable failed, trying MSI.\n"); qdev->intr_count = 1; - qlge_irq_type = MSI_IRQ; + irq_type = MSI_IRQ; } else if (err == 0) { set_bit(QL_MSIX_ENABLED, &qdev->flags); QPRINTK(qdev, IFUP, INFO, @@ -2912,7 +2912,7 @@ static void ql_enable_msix(struct ql_adapter *qdev) } msi: qdev->intr_count = 1; - if (qlge_irq_type == MSI_IRQ) { + if (irq_type == MSI_IRQ) { if (!pci_enable_msi(qdev->pdev)) { set_bit(QL_MSI_ENABLED, &qdev->flags); QPRINTK(qdev, IFUP, INFO, @@ -2920,7 +2920,7 @@ static void ql_enable_msix(struct ql_adapter *qdev) return; } } - qlge_irq_type = LEG_IRQ; + irq_type = LEG_IRQ; QPRINTK(qdev, IFUP, DEBUG, "Running with legacy interrupts.\n"); } @@ -3514,6 +3514,9 @@ int ql_wol(struct ql_adapter *qdev) } if (qdev->wol) { + /* Reroute all packets to Management Interface */ + ql_write32(qdev, MGMT_RCV_CFG, (MGMT_RCV_CFG_RM | + (MGMT_RCV_CFG_RM << 16))); wol |= MB_WOL_MODE_ON; status = ql_mb_wol_mode(qdev, wol); QPRINTK(qdev, DRV, ERR, "WOL %s (wol code 0x%x) on %s\n", @@ -3714,10 +3717,6 @@ static int qlge_open(struct net_device *ndev) int err = 0; struct ql_adapter *qdev = netdev_priv(ndev); - err = ql_adapter_reset(qdev); - if (err) - return err; - err = ql_configure_rings(qdev); if (err) return err; @@ -4146,8 +4145,6 @@ static int __devinit ql_init_device(struct pci_dev *pdev, goto err_out; } - /* Set PCIe reset type for EEH to fundamental. */ - pdev->needs_freset = 1; pci_save_state(pdev); qdev->reg_base = ioremap_nocache(pci_resource_start(pdev, 1), diff --git a/trunk/drivers/net/qlge/qlge_mpi.c b/trunk/drivers/net/qlge/qlge_mpi.c index e2b2286102d4..f5619fe87bb2 100644 --- a/trunk/drivers/net/qlge/qlge_mpi.c +++ b/trunk/drivers/net/qlge/qlge_mpi.c @@ -483,7 +483,7 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) /* Wait for the interrupt to come in. */ status = ql_wait_mbx_cmd_cmplt(qdev); if (status) - continue; + goto end; /* Process the event. If it's an AEN, it * will be handled in-line or a worker diff --git a/trunk/drivers/net/r8169.c b/trunk/drivers/net/r8169.c index 1b0aa4cf89bc..1f7946c7d4e8 100644 --- a/trunk/drivers/net/r8169.c +++ b/trunk/drivers/net/r8169.c @@ -3379,7 +3379,7 @@ static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) { /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz + 1); + RTL_W16(RxMaxSize, rx_buf_sz); } static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) diff --git a/trunk/drivers/net/sky2.c b/trunk/drivers/net/sky2.c index a3d99913f184..1729ebf5de9c 100644 --- a/trunk/drivers/net/sky2.c +++ b/trunk/drivers/net/sky2.c @@ -4651,8 +4651,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev, goto err_out_free_netdev; } - netif_carrier_off(dev); - netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT); err = request_irq(pdev->irq, sky2_intr, diff --git a/trunk/drivers/net/slip.c b/trunk/drivers/net/slip.c index ccfe45924fd9..e17c535a577e 100644 --- a/trunk/drivers/net/slip.c +++ b/trunk/drivers/net/slip.c @@ -79,7 +79,6 @@ #include #include #include -#include #include #include #include "slip.h" @@ -1169,27 +1168,6 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file, } } -#ifdef CONFIG_COMPAT -static long slip_compat_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case SIOCGIFNAME: - case SIOCGIFENCAP: - case SIOCSIFENCAP: - case SIOCSIFHWADDR: - case SIOCSKEEPALIVE: - case SIOCGKEEPALIVE: - case SIOCSOUTFILL: - case SIOCGOUTFILL: - return slip_ioctl(tty, file, cmd, - (unsigned long)compat_ptr(arg)); - } - - return -ENOIOCTLCMD; -} -#endif - /* VSV changes start here */ #ifdef CONFIG_SLIP_SMART /* function do_ioctl called from net/core/dev.c @@ -1282,9 +1260,6 @@ static struct tty_ldisc_ops sl_ldisc = { .close = slip_close, .hangup = slip_hangup, .ioctl = slip_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = slip_compat_ioctl, -#endif .receive_buf = slip_receive_buf, .write_wakeup = slip_write_wakeup, }; diff --git a/trunk/drivers/net/spider_net.c b/trunk/drivers/net/spider_net.c index 782910cf220f..90e663f4515c 100644 --- a/trunk/drivers/net/spider_net.c +++ b/trunk/drivers/net/spider_net.c @@ -57,7 +57,6 @@ MODULE_AUTHOR("Utz Bacher and Jens Osterkamp " \ MODULE_DESCRIPTION("Spider Southbridge Gigabit Ethernet driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(VERSION); -MODULE_FIRMWARE(SPIDER_NET_FIRMWARE_NAME); static int rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_DEFAULT; static int tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_DEFAULT; diff --git a/trunk/drivers/net/tokenring/ibmtr.c b/trunk/drivers/net/tokenring/ibmtr.c index 6a3c7510afd9..525bbc5b9c9d 100644 --- a/trunk/drivers/net/tokenring/ibmtr.c +++ b/trunk/drivers/net/tokenring/ibmtr.c @@ -1143,16 +1143,9 @@ static void dir_open_adapter (struct net_device *dev) } else { char **prphase = printphase; char **prerror = printerror; - int pnr = err / 16 - 1; - int enr = err % 16 - 1; DPRINTK("TR Adapter misc open failure, error code = "); - if (pnr < 0 || pnr >= ARRAY_SIZE(printphase) || - enr < 0 || - enr >= ARRAY_SIZE(printerror)) - printk("0x%x, invalid Phase/Error.", err); - else - printk("0x%x, Phase: %s, Error: %s\n", err, - prphase[pnr], prerror[enr]); + printk("0x%x, Phase: %s, Error: %s\n", + err, prphase[err/16 -1], prerror[err%16 -1]); printk(" retrying after %ds delay...\n", TR_RETRY_INTERVAL/HZ); } diff --git a/trunk/drivers/net/tokenring/tms380tr.c b/trunk/drivers/net/tokenring/tms380tr.c index fa152144aacf..a7b6888829b5 100644 --- a/trunk/drivers/net/tokenring/tms380tr.c +++ b/trunk/drivers/net/tokenring/tms380tr.c @@ -1364,8 +1364,6 @@ static int tms380tr_reset_adapter(struct net_device *dev) return (-1); } -MODULE_FIRMWARE("tms380tr.bin"); - /* * Starts bring up diagnostics of token ring adapter and evaluates * diagnostic results. diff --git a/trunk/drivers/net/tun.c b/trunk/drivers/net/tun.c index 01e99f22210e..9c59a82784dc 100644 --- a/trunk/drivers/net/tun.c +++ b/trunk/drivers/net/tun.c @@ -53,7 +53,6 @@ #include #include #include -#include #include #include #include @@ -1110,8 +1109,8 @@ static int set_offload(struct net_device *dev, unsigned long arg) return 0; } -static long __tun_chr_ioctl(struct file *file, unsigned int cmd, - unsigned long arg, int ifreq_len) +static long tun_chr_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { struct tun_file *tfile = file->private_data; struct tun_struct *tun; @@ -1121,7 +1120,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, int ret; if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) - if (copy_from_user(&ifr, argp, ifreq_len)) + if (copy_from_user(&ifr, argp, sizeof ifr)) return -EFAULT; if (cmd == TUNGETFEATURES) { @@ -1144,7 +1143,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, if (ret) goto unlock; - if (copy_to_user(argp, &ifr, ifreq_len)) + if (copy_to_user(argp, &ifr, sizeof(ifr))) ret = -EFAULT; goto unlock; } @@ -1162,7 +1161,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, if (ret) break; - if (copy_to_user(argp, &ifr, ifreq_len)) + if (copy_to_user(argp, &ifr, sizeof(ifr))) ret = -EFAULT; break; @@ -1236,7 +1235,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, /* Get hw addres */ memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN); ifr.ifr_hwaddr.sa_family = tun->dev->type; - if (copy_to_user(argp, &ifr, ifreq_len)) + if (copy_to_user(argp, &ifr, sizeof ifr)) ret = -EFAULT; break; @@ -1275,41 +1274,6 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, return ret; } -static long tun_chr_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - return __tun_chr_ioctl(file, cmd, arg, sizeof (struct ifreq)); -} - -#ifdef CONFIG_COMPAT -static long tun_chr_compat_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case TUNSETIFF: - case TUNGETIFF: - case TUNSETTXFILTER: - case TUNGETSNDBUF: - case TUNSETSNDBUF: - case SIOCGIFHWADDR: - case SIOCSIFHWADDR: - arg = (unsigned long)compat_ptr(arg); - break; - default: - arg = (compat_ulong_t)arg; - break; - } - - /* - * compat_ifreq is shorter than ifreq, so we must not access beyond - * the end of that structure. All fields that are used in this - * driver are compatible though, we don't need to convert the - * contents. - */ - return __tun_chr_ioctl(file, cmd, arg, sizeof(struct compat_ifreq)); -} -#endif /* CONFIG_COMPAT */ - static int tun_chr_fasync(int fd, struct file *file, int on) { struct tun_struct *tun = tun_get(file); @@ -1392,10 +1356,7 @@ static const struct file_operations tun_fops = { .write = do_sync_write, .aio_write = tun_chr_aio_write, .poll = tun_chr_poll, - .unlocked_ioctl = tun_chr_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = tun_chr_compat_ioctl, -#endif + .unlocked_ioctl = tun_chr_ioctl, .open = tun_chr_open, .release = tun_chr_close, .fasync = tun_chr_fasync diff --git a/trunk/drivers/net/usb/Kconfig b/trunk/drivers/net/usb/Kconfig index 32d93564a74d..c47237c2d638 100644 --- a/trunk/drivers/net/usb/Kconfig +++ b/trunk/drivers/net/usb/Kconfig @@ -174,7 +174,7 @@ config USB_NET_CDCETHER * Ericsson Mobile Broadband Module (all variants) * Motorola (DM100 and SB4100) * Broadcom Cable Modem (reference design) - * Toshiba (PCX1100U and F3507g/F3607gw) + * Toshiba (PCX1100U and F3507g) * ... This driver creates an interface named "ethX", where X depends on diff --git a/trunk/drivers/net/usb/asix.c b/trunk/drivers/net/usb/asix.c index 1bef39a60a62..6ce7f775bb74 100644 --- a/trunk/drivers/net/usb/asix.c +++ b/trunk/drivers/net/usb/asix.c @@ -1327,7 +1327,7 @@ static const struct driver_info ax8817x_info = { .status = asix_status, .link_reset = ax88172_link_reset, .reset = ax88172_link_reset, - .flags = FLAG_ETHER | FLAG_LINK_INTR, + .flags = FLAG_ETHER, .data = 0x00130103, }; @@ -1337,7 +1337,7 @@ static const struct driver_info dlink_dub_e100_info = { .status = asix_status, .link_reset = ax88172_link_reset, .reset = ax88172_link_reset, - .flags = FLAG_ETHER | FLAG_LINK_INTR, + .flags = FLAG_ETHER, .data = 0x009f9d9f, }; @@ -1347,7 +1347,7 @@ static const struct driver_info netgear_fa120_info = { .status = asix_status, .link_reset = ax88172_link_reset, .reset = ax88172_link_reset, - .flags = FLAG_ETHER | FLAG_LINK_INTR, + .flags = FLAG_ETHER, .data = 0x00130103, }; @@ -1357,7 +1357,7 @@ static const struct driver_info hawking_uf200_info = { .status = asix_status, .link_reset = ax88172_link_reset, .reset = ax88172_link_reset, - .flags = FLAG_ETHER | FLAG_LINK_INTR, + .flags = FLAG_ETHER, .data = 0x001f1d1f, }; @@ -1367,7 +1367,7 @@ static const struct driver_info ax88772_info = { .status = asix_status, .link_reset = ax88772_link_reset, .reset = ax88772_link_reset, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = asix_rx_fixup, .tx_fixup = asix_tx_fixup, }; @@ -1378,7 +1378,7 @@ static const struct driver_info ax88178_info = { .status = asix_status, .link_reset = ax88178_link_reset, .reset = ax88178_link_reset, - .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = asix_rx_fixup, .tx_fixup = asix_tx_fixup, }; diff --git a/trunk/drivers/net/usb/cdc_ether.c b/trunk/drivers/net/usb/cdc_ether.c index 7ec24c9b2535..71e65fc10e6f 100644 --- a/trunk/drivers/net/usb/cdc_ether.c +++ b/trunk/drivers/net/usb/cdc_ether.c @@ -413,7 +413,7 @@ static int cdc_bind(struct usbnet *dev, struct usb_interface *intf) static const struct driver_info cdc_info = { .description = "CDC Ethernet Device", - .flags = FLAG_ETHER | FLAG_LINK_INTR, + .flags = FLAG_ETHER, // .check_connect = cdc_check_connect, .bind = cdc_bind, .unbind = usbnet_cdc_unbind, @@ -551,29 +551,9 @@ static const struct usb_device_id products [] = { USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1904, USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &mbm_info, -}, { - /* Ericsson F3607gw ver 2 */ - USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1905, USB_CLASS_COMM, - USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &mbm_info, -}, { - /* Ericsson F3607gw ver 3 */ - USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1906, USB_CLASS_COMM, - USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &mbm_info, }, { /* Ericsson F3307 */ - USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x190a, USB_CLASS_COMM, - USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &mbm_info, -}, { - /* Ericsson F3307 ver 2 */ - USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1909, USB_CLASS_COMM, - USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &mbm_info, -}, { - /* Ericsson C3607w */ - USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1049, USB_CLASS_COMM, + USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1906, USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &mbm_info, }, { @@ -581,31 +561,11 @@ static const struct usb_device_id products [] = { USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130b, USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &mbm_info, -}, { - /* Toshiba F3607gw */ - USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130c, USB_CLASS_COMM, - USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &mbm_info, -}, { - /* Toshiba F3607gw ver 2 */ - USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x1311, USB_CLASS_COMM, - USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &mbm_info, }, { /* Dell F3507g */ USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8147, USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &mbm_info, -}, { - /* Dell F3607gw */ - USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8183, USB_CLASS_COMM, - USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &mbm_info, -}, { - /* Dell F3607gw ver 2 */ - USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8184, USB_CLASS_COMM, - USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &mbm_info, }, { }, // END }; diff --git a/trunk/drivers/net/usb/dm9601.c b/trunk/drivers/net/usb/dm9601.c index 3d406f9b2f29..a2b30a10064f 100644 --- a/trunk/drivers/net/usb/dm9601.c +++ b/trunk/drivers/net/usb/dm9601.c @@ -611,7 +611,7 @@ static int dm9601_link_reset(struct usbnet *dev) static const struct driver_info dm9601_info = { .description = "Davicom DM9601 USB Ethernet", - .flags = FLAG_ETHER | FLAG_LINK_INTR, + .flags = FLAG_ETHER, .bind = dm9601_bind, .rx_fixup = dm9601_rx_fixup, .tx_fixup = dm9601_tx_fixup, diff --git a/trunk/drivers/net/usb/usbnet.c b/trunk/drivers/net/usb/usbnet.c index 04f3f289e87c..378da8c938fe 100644 --- a/trunk/drivers/net/usb/usbnet.c +++ b/trunk/drivers/net/usb/usbnet.c @@ -1352,11 +1352,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) // ok, it's ready to go. usb_set_intfdata (udev, dev); + // start as if the link is up netif_device_attach (net); - if (dev->driver_info->flags & FLAG_LINK_INTR) - netif_carrier_off(net); - return 0; out3: diff --git a/trunk/drivers/net/veth.c b/trunk/drivers/net/veth.c index 2d657f2314cb..9bed694cd215 100644 --- a/trunk/drivers/net/veth.c +++ b/trunk/drivers/net/veth.c @@ -340,7 +340,7 @@ static int veth_validate(struct nlattr *tb[], struct nlattr *data[]) static struct rtnl_link_ops veth_link_ops; -static int veth_newlink(struct net *src_net, struct net_device *dev, +static int veth_newlink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { int err; @@ -348,7 +348,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, struct veth_priv *priv; char ifname[IFNAMSIZ]; struct nlattr *peer_tb[IFLA_MAX + 1], **tbp; - struct net *net; /* * create and register peer first @@ -381,22 +380,14 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, else snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d"); - net = rtnl_link_get_net(src_net, tbp); - if (IS_ERR(net)) - return PTR_ERR(net); - - peer = rtnl_create_link(src_net, net, ifname, &veth_link_ops, tbp); - if (IS_ERR(peer)) { - put_net(net); + peer = rtnl_create_link(dev_net(dev), ifname, &veth_link_ops, tbp); + if (IS_ERR(peer)) return PTR_ERR(peer); - } if (tbp[IFLA_ADDRESS] == NULL) random_ether_addr(peer->dev_addr); err = register_netdevice(peer); - put_net(net); - net = NULL; if (err < 0) goto err_register_peer; diff --git a/trunk/drivers/net/virtio_net.c b/trunk/drivers/net/virtio_net.c index 22a8ca5d67d5..95274678fe45 100644 --- a/trunk/drivers/net/virtio_net.c +++ b/trunk/drivers/net/virtio_net.c @@ -996,7 +996,7 @@ static unsigned int features[] = { VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, }; -static struct virtio_driver virtio_net_driver = { +static struct virtio_driver virtio_net = { .feature_table = features, .feature_table_size = ARRAY_SIZE(features), .driver.name = KBUILD_MODNAME, @@ -1009,12 +1009,12 @@ static struct virtio_driver virtio_net_driver = { static int __init init(void) { - return register_virtio_driver(&virtio_net_driver); + return register_virtio_driver(&virtio_net); } static void __exit fini(void) { - unregister_virtio_driver(&virtio_net_driver); + unregister_virtio_driver(&virtio_net); } module_init(init); module_exit(fini); diff --git a/trunk/drivers/net/wan/x25_asy.c b/trunk/drivers/net/wan/x25_asy.c index 3c325d77939b..27945049c9e1 100644 --- a/trunk/drivers/net/wan/x25_asy.c +++ b/trunk/drivers/net/wan/x25_asy.c @@ -33,7 +33,6 @@ #include #include #include -#include #include "x25_asy.h" #include @@ -706,21 +705,6 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file, } } -#ifdef CONFIG_COMPAT -static long x25_asy_compat_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case SIOCGIFNAME: - case SIOCSIFHWADDR: - return x25_asy_ioctl(tty, file, cmd, - (unsigned long)compat_ptr(arg)); - } - - return -ENOIOCTLCMD; -} -#endif - static int x25_asy_open_dev(struct net_device *dev) { struct x25_asy *sl = netdev_priv(dev); @@ -770,9 +754,6 @@ static struct tty_ldisc_ops x25_ldisc = { .open = x25_asy_open_tty, .close = x25_asy_close_tty, .ioctl = x25_asy_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = x25_asy_compat_ioctl, -#endif .receive_buf = x25_asy_receive_buf, .write_wakeup = x25_asy_write_wakeup, }; diff --git a/trunk/drivers/net/wimax/i2400m/control.c b/trunk/drivers/net/wimax/i2400m/control.c index 944945540391..07308686dbcf 100644 --- a/trunk/drivers/net/wimax/i2400m/control.c +++ b/trunk/drivers/net/wimax/i2400m/control.c @@ -54,7 +54,7 @@ * i2400m_set_init_config() * i2400m_cmd_get_state() * i2400m_dev_shutdown() Called by i2400m_dev_stop() - * i2400m_reset() + * i2400m->bus_reset() * * i2400m_{cmd,get,set}_*() * i2400m_msg_to_dev() @@ -82,13 +82,6 @@ #define D_SUBMODULE control #include "debug-levels.h" -int i2400m_passive_mode; /* 0 (passive mode disabled) by default */ -module_param_named(passive_mode, i2400m_passive_mode, int, 0644); -MODULE_PARM_DESC(passive_mode, - "If true, the driver will not do any device setup " - "and leave it up to user space, who must be properly " - "setup."); - /* * Return if a TLV is of a give type and size @@ -270,7 +263,7 @@ int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *l3l4_hdr, if (status == 0) return 0; - if (status >= ARRAY_SIZE(ms_to_errno)) { + if (status > ARRAY_SIZE(ms_to_errno)) { str = "unknown status code"; result = -EBADR; } else { @@ -343,7 +336,7 @@ void i2400m_report_tlv_system_state(struct i2400m *i2400m, /* Huh? just in case, shut it down */ dev_err(dev, "HW BUG? unknown state %u: shutting down\n", i2400m_state); - i2400m_reset(i2400m, I2400M_RT_WARM); + i2400m->bus_reset(i2400m, I2400M_RT_WARM); break; }; d_fnend(3, dev, "(i2400m %p ss %p [%u]) = void\n", @@ -1342,8 +1335,6 @@ int i2400m_dev_initialize(struct i2400m *i2400m) unsigned argc = 0; d_fnstart(3, dev, "(i2400m %p)\n", i2400m); - if (i2400m_passive_mode) - goto out_passive; /* Disable idle mode? (enabled by default) */ if (i2400m_idle_mode_disabled) { if (i2400m_le_v1_3(i2400m)) { @@ -1386,7 +1377,6 @@ int i2400m_dev_initialize(struct i2400m *i2400m) result = i2400m_set_init_config(i2400m, args, argc); if (result < 0) goto error; -out_passive: /* * Update state: Here it just calls a get state; parsing the * result (System State TLV and RF Status TLV [done in the rx diff --git a/trunk/drivers/net/wimax/i2400m/debugfs.c b/trunk/drivers/net/wimax/i2400m/debugfs.c index b1aec3e1892f..9b81af3f80a9 100644 --- a/trunk/drivers/net/wimax/i2400m/debugfs.c +++ b/trunk/drivers/net/wimax/i2400m/debugfs.c @@ -214,7 +214,7 @@ int debugfs_i2400m_reset_set(void *data, u64 val) case I2400M_RT_WARM: case I2400M_RT_COLD: case I2400M_RT_BUS: - result = i2400m_reset(i2400m, rt); + result = i2400m->bus_reset(i2400m, rt); if (result >= 0) result = 0; default: diff --git a/trunk/drivers/net/wimax/i2400m/driver.c b/trunk/drivers/net/wimax/i2400m/driver.c index 96a615fe09de..304f0443ca4b 100644 --- a/trunk/drivers/net/wimax/i2400m/driver.c +++ b/trunk/drivers/net/wimax/i2400m/driver.c @@ -41,10 +41,8 @@ * __i2400m_dev_start() * * i2400m_setup() - * i2400m->bus_setup() * i2400m_bootrom_init() * register_netdev() - * wimax_dev_add() * i2400m_dev_start() * __i2400m_dev_start() * i2400m_dev_bootstrap() @@ -52,15 +50,15 @@ * i2400m->bus_dev_start() * i2400m_firmware_check() * i2400m_check_mac_addr() + * wimax_dev_add() * * i2400m_release() + * wimax_dev_rm() * i2400m_dev_stop() * __i2400m_dev_stop() * i2400m_dev_shutdown() * i2400m->bus_dev_stop() * i2400m_tx_release() - * i2400m->bus_release() - * wimax_dev_rm() * unregister_netdev() */ #include "i2400m.h" @@ -68,7 +66,6 @@ #include #include #include -#include #define D_SUBMODULE driver #include "debug-levels.h" @@ -93,39 +90,76 @@ MODULE_PARM_DESC(power_save_disabled, "False by default (so the device is told to do power " "saving)."); -static char i2400m_debug_params[128]; -module_param_string(debug, i2400m_debug_params, sizeof(i2400m_debug_params), - 0644); -MODULE_PARM_DESC(debug, - "String of space-separated NAME:VALUE pairs, where NAMEs " - "are the different debug submodules and VALUE are the " - "initial debug value to set."); - -static char i2400m_barkers_params[128]; -module_param_string(barkers, i2400m_barkers_params, - sizeof(i2400m_barkers_params), 0644); -MODULE_PARM_DESC(barkers, - "String of comma-separated 32-bit values; each is " - "recognized as the value the device sends as a reboot " - "signal; values are appended to a list--setting one value " - "as zero cleans the existing list and starts a new one."); - -static -struct i2400m_work *__i2400m_work_setup( - struct i2400m *i2400m, void (*fn)(struct work_struct *), - gfp_t gfp_flags, const void *pl, size_t pl_size) +/** + * i2400m_queue_work - schedule work on a i2400m's queue + * + * @i2400m: device descriptor + * + * @fn: function to run to execute work. It gets passed a 'struct + * work_struct' that is wrapped in a 'struct i2400m_work'. Once + * done, you have to (1) i2400m_put(i2400m_work->i2400m) and then + * (2) kfree(i2400m_work). + * + * @gfp_flags: GFP flags for memory allocation. + * + * @pl: pointer to a payload buffer that you want to pass to the _work + * function. Use this to pack (for example) a struct with extra + * arguments. + * + * @pl_size: size of the payload buffer. + * + * We do this quite often, so this just saves typing; allocate a + * wrapper for a i2400m, get a ref to it, pack arguments and launch + * the work. + * + * A usual workflow is: + * + * struct my_work_args { + * void *something; + * int whatever; + * }; + * ... + * + * struct my_work_args my_args = { + * .something = FOO, + * .whaetever = BLAH + * }; + * i2400m_queue_work(i2400m, 1, my_work_function, GFP_KERNEL, + * &args, sizeof(args)) + * + * And now the work function can unpack the arguments and call the + * real function (or do the job itself): + * + * static + * void my_work_fn((struct work_struct *ws) + * { + * struct i2400m_work *iw = + * container_of(ws, struct i2400m_work, ws); + * struct my_work_args *my_args = (void *) iw->pl; + * + * my_work(iw->i2400m, my_args->something, my_args->whatevert); + * } + */ +int i2400m_queue_work(struct i2400m *i2400m, + void (*fn)(struct work_struct *), gfp_t gfp_flags, + const void *pl, size_t pl_size) { + int result; struct i2400m_work *iw; + BUG_ON(i2400m->work_queue == NULL); + result = -ENOMEM; iw = kzalloc(sizeof(*iw) + pl_size, gfp_flags); if (iw == NULL) - return NULL; + goto error_kzalloc; iw->i2400m = i2400m_get(i2400m); - iw->pl_size = pl_size; memcpy(iw->pl, pl, pl_size); INIT_WORK(&iw->ws, fn); - return iw; + result = queue_work(i2400m->work_queue, &iw->ws); +error_kzalloc: + return result; } +EXPORT_SYMBOL_GPL(i2400m_queue_work); /* @@ -141,19 +175,21 @@ struct i2400m_work *__i2400m_work_setup( * it should not happen. */ int i2400m_schedule_work(struct i2400m *i2400m, - void (*fn)(struct work_struct *), gfp_t gfp_flags, - const void *pl, size_t pl_size) + void (*fn)(struct work_struct *), gfp_t gfp_flags) { int result; struct i2400m_work *iw; result = -ENOMEM; - iw = __i2400m_work_setup(i2400m, fn, gfp_flags, pl, pl_size); - if (iw != NULL) { - result = schedule_work(&iw->ws); - if (WARN_ON(result == 0)) - result = -ENXIO; - } + iw = kzalloc(sizeof(*iw), gfp_flags); + if (iw == NULL) + goto error_kzalloc; + iw->i2400m = i2400m_get(i2400m); + INIT_WORK(&iw->ws, fn); + result = schedule_work(&iw->ws); + if (result == 0) + result = -ENXIO; +error_kzalloc: return result; } @@ -255,7 +291,7 @@ int i2400m_op_reset(struct wimax_dev *wimax_dev) mutex_lock(&i2400m->init_mutex); i2400m->reset_ctx = &ctx; mutex_unlock(&i2400m->init_mutex); - result = i2400m_reset(i2400m, I2400M_RT_WARM); + result = i2400m->bus_reset(i2400m, I2400M_RT_WARM); if (result < 0) goto out; result = wait_for_completion_timeout(&ctx.completion, 4*HZ); @@ -384,15 +420,9 @@ int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags) dev_err(dev, "cannot create workqueue\n"); goto error_create_workqueue; } - if (i2400m->bus_dev_start) { - result = i2400m->bus_dev_start(i2400m); - if (result < 0) - goto error_bus_dev_start; - } - i2400m->ready = 1; - wmb(); /* see i2400m->ready's documentation */ - /* process pending reports from the device */ - queue_work(i2400m->work_queue, &i2400m->rx_report_ws); + result = i2400m->bus_dev_start(i2400m); + if (result < 0) + goto error_bus_dev_start; result = i2400m_firmware_check(i2400m); /* fw versions ok? */ if (result < 0) goto error_fw_check; @@ -400,6 +430,8 @@ int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags) result = i2400m_check_mac_addr(i2400m); if (result < 0) goto error_check_mac_addr; + i2400m->ready = 1; + wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED); result = i2400m_dev_initialize(i2400m); if (result < 0) goto error_dev_initialize; @@ -411,12 +443,8 @@ int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags) error_dev_initialize: error_check_mac_addr: - i2400m->ready = 0; - wmb(); /* see i2400m->ready's documentation */ - flush_workqueue(i2400m->work_queue); error_fw_check: - if (i2400m->bus_dev_stop) - i2400m->bus_dev_stop(i2400m); + i2400m->bus_dev_stop(i2400m); error_bus_dev_start: destroy_workqueue(i2400m->work_queue); error_create_workqueue: @@ -438,15 +466,11 @@ int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags) static int i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri bm_flags) { - int result = 0; + int result; mutex_lock(&i2400m->init_mutex); /* Well, start the device */ - if (i2400m->updown == 0) { - result = __i2400m_dev_start(i2400m, bm_flags); - if (result >= 0) { - i2400m->updown = 1; - wmb(); /* see i2400m->updown's documentation */ - } - } + result = __i2400m_dev_start(i2400m, bm_flags); + if (result >= 0) + i2400m->updown = 1; mutex_unlock(&i2400m->init_mutex); return result; } @@ -471,20 +495,9 @@ void __i2400m_dev_stop(struct i2400m *i2400m) d_fnstart(3, dev, "(i2400m %p)\n", i2400m); wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING); - i2400m_msg_to_dev_cancel_wait(i2400m, -EL3RST); - complete(&i2400m->msg_completion); - i2400m_net_wake_stop(i2400m); i2400m_dev_shutdown(i2400m); - /* - * Make sure no report hooks are running *before* we stop the - * communication infrastructure with the device. - */ - i2400m->ready = 0; /* nobody can queue work anymore */ - wmb(); /* see i2400m->ready's documentation */ - flush_workqueue(i2400m->work_queue); - - if (i2400m->bus_dev_stop) - i2400m->bus_dev_stop(i2400m); + i2400m->ready = 0; + i2400m->bus_dev_stop(i2400m); destroy_workqueue(i2400m->work_queue); i2400m_rx_release(i2400m); i2400m_tx_release(i2400m); @@ -505,138 +518,11 @@ void i2400m_dev_stop(struct i2400m *i2400m) if (i2400m->updown) { __i2400m_dev_stop(i2400m); i2400m->updown = 0; - wmb(); /* see i2400m->updown's documentation */ } mutex_unlock(&i2400m->init_mutex); } -/* - * Listen to PM events to cache the firmware before suspend/hibernation - * - * When the device comes out of suspend, it might go into reset and - * firmware has to be uploaded again. At resume, most of the times, we - * can't load firmware images from disk, so we need to cache it. - * - * i2400m_fw_cache() will allocate a kobject and attach the firmware - * to it; that way we don't have to worry too much about the fw loader - * hitting a race condition. - * - * Note: modus operandi stolen from the Orinoco driver; thx. - */ -static -int i2400m_pm_notifier(struct notifier_block *notifier, - unsigned long pm_event, - void *unused) -{ - struct i2400m *i2400m = - container_of(notifier, struct i2400m, pm_notifier); - struct device *dev = i2400m_dev(i2400m); - - d_fnstart(3, dev, "(i2400m %p pm_event %lx)\n", i2400m, pm_event); - switch (pm_event) { - case PM_HIBERNATION_PREPARE: - case PM_SUSPEND_PREPARE: - i2400m_fw_cache(i2400m); - break; - case PM_POST_RESTORE: - /* Restore from hibernation failed. We need to clean - * up in exactly the same way, so fall through. */ - case PM_POST_HIBERNATION: - case PM_POST_SUSPEND: - i2400m_fw_uncache(i2400m); - break; - - case PM_RESTORE_PREPARE: - default: - break; - } - d_fnend(3, dev, "(i2400m %p pm_event %lx) = void\n", i2400m, pm_event); - return NOTIFY_DONE; -} - - -/* - * pre-reset is called before a device is going on reset - * - * This has to be followed by a call to i2400m_post_reset(), otherwise - * bad things might happen. - */ -int i2400m_pre_reset(struct i2400m *i2400m) -{ - int result; - struct device *dev = i2400m_dev(i2400m); - - d_fnstart(3, dev, "(i2400m %p)\n", i2400m); - d_printf(1, dev, "pre-reset shut down\n"); - - result = 0; - mutex_lock(&i2400m->init_mutex); - if (i2400m->updown) { - netif_tx_disable(i2400m->wimax_dev.net_dev); - __i2400m_dev_stop(i2400m); - result = 0; - /* down't set updown to zero -- this way - * post_reset can restore properly */ - } - mutex_unlock(&i2400m->init_mutex); - if (i2400m->bus_release) - i2400m->bus_release(i2400m); - d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); - return result; -} -EXPORT_SYMBOL_GPL(i2400m_pre_reset); - - -/* - * Restore device state after a reset - * - * Do the work needed after a device reset to bring it up to the same - * state as it was before the reset. - * - * NOTE: this requires i2400m->init_mutex taken - */ -int i2400m_post_reset(struct i2400m *i2400m) -{ - int result = 0; - struct device *dev = i2400m_dev(i2400m); - - d_fnstart(3, dev, "(i2400m %p)\n", i2400m); - d_printf(1, dev, "post-reset start\n"); - if (i2400m->bus_setup) { - result = i2400m->bus_setup(i2400m); - if (result < 0) { - dev_err(dev, "bus-specific setup failed: %d\n", - result); - goto error_bus_setup; - } - } - mutex_lock(&i2400m->init_mutex); - if (i2400m->updown) { - result = __i2400m_dev_start( - i2400m, I2400M_BRI_SOFT | I2400M_BRI_MAC_REINIT); - if (result < 0) - goto error_dev_start; - } - mutex_unlock(&i2400m->init_mutex); - d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); - return result; - -error_dev_start: - if (i2400m->bus_release) - i2400m->bus_release(i2400m); -error_bus_setup: - /* even if the device was up, it could not be recovered, so we - * mark it as down. */ - i2400m->updown = 0; - wmb(); /* see i2400m->updown's documentation */ - mutex_unlock(&i2400m->init_mutex); - d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); - return result; -} -EXPORT_SYMBOL_GPL(i2400m_post_reset); - - /* * The device has rebooted; fix up the device and the driver * @@ -656,69 +542,56 @@ EXPORT_SYMBOL_GPL(i2400m_post_reset); * _stop()], don't do anything, let it fail and handle it. * * This function is ran always in a thread context - * - * This function gets passed, as payload to i2400m_work() a 'const - * char *' ptr with a "reason" why the reset happened (for messages). */ static void __i2400m_dev_reset_handle(struct work_struct *ws) { int result; struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws); - const char *reason; struct i2400m *i2400m = iw->i2400m; struct device *dev = i2400m_dev(i2400m); + enum wimax_st wimax_state; struct i2400m_reset_ctx *ctx = i2400m->reset_ctx; - if (WARN_ON(iw->pl_size != sizeof(reason))) - reason = "SW BUG: reason n/a"; - else - memcpy(&reason, iw->pl, sizeof(reason)); - - d_fnstart(3, dev, "(ws %p i2400m %p reason %s)\n", ws, i2400m, reason); - + d_fnstart(3, dev, "(ws %p i2400m %p)\n", ws, i2400m); result = 0; if (mutex_trylock(&i2400m->init_mutex) == 0) { /* We are still in i2400m_dev_start() [let it fail] or * i2400m_dev_stop() [we are shutting down anyway, so * ignore it] or we are resetting somewhere else. */ - dev_err(dev, "device rebooted somewhere else?\n"); + dev_err(dev, "device rebooted\n"); i2400m_msg_to_dev_cancel_wait(i2400m, -EL3RST); complete(&i2400m->msg_completion); goto out; } - if (i2400m->updown == 0) { - dev_info(dev, "%s: device is down, doing nothing\n", reason); - goto out_unlock; + wimax_state = wimax_state_get(&i2400m->wimax_dev); + if (wimax_state < WIMAX_ST_UNINITIALIZED) { + dev_info(dev, "device rebooted: it is down, ignoring\n"); + goto out_unlock; /* ifconfig up/down wasn't called */ } - dev_err(dev, "%s: reinitializing driver\n", reason); + dev_err(dev, "device rebooted: reinitializing driver\n"); __i2400m_dev_stop(i2400m); + i2400m->updown = 0; result = __i2400m_dev_start(i2400m, I2400M_BRI_SOFT | I2400M_BRI_MAC_REINIT); if (result < 0) { - i2400m->updown = 0; - wmb(); /* see i2400m->updown's documentation */ - dev_err(dev, "%s: cannot start the device: %d\n", - reason, result); - result = -EUCLEAN; - } + dev_err(dev, "device reboot: cannot start the device: %d\n", + result); + result = i2400m->bus_reset(i2400m, I2400M_RT_BUS); + if (result >= 0) + result = -ENODEV; + } else + i2400m->updown = 1; out_unlock: if (i2400m->reset_ctx) { ctx->result = result; complete(&ctx->completion); } mutex_unlock(&i2400m->init_mutex); - if (result == -EUCLEAN) { - /* ops, need to clean up [w/ init_mutex not held] */ - result = i2400m_reset(i2400m, I2400M_RT_BUS); - if (result >= 0) - result = -ENODEV; - } out: i2400m_put(i2400m); kfree(iw); - d_fnend(3, dev, "(ws %p i2400m %p reason %s) = void\n", - ws, i2400m, reason); + d_fnend(3, dev, "(ws %p i2400m %p) = void\n", ws, i2400m); return; } @@ -735,104 +608,16 @@ void __i2400m_dev_reset_handle(struct work_struct *ws) * reinitializing the driver to handle the reset, calling into the * bus-specific functions ops as needed. */ -int i2400m_dev_reset_handle(struct i2400m *i2400m, const char *reason) +int i2400m_dev_reset_handle(struct i2400m *i2400m) { i2400m->boot_mode = 1; wmb(); /* Make sure i2400m_msg_to_dev() sees boot_mode */ return i2400m_schedule_work(i2400m, __i2400m_dev_reset_handle, - GFP_ATOMIC, &reason, sizeof(reason)); + GFP_ATOMIC); } EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle); -/* - * Alloc the command and ack buffers for boot mode - * - * Get the buffers needed to deal with boot mode messages. These - * buffers need to be allocated before the sdio recieve irq is setup. - */ -static -int i2400m_bm_buf_alloc(struct i2400m *i2400m) -{ - int result; - - result = -ENOMEM; - i2400m->bm_cmd_buf = kzalloc(I2400M_BM_CMD_BUF_SIZE, GFP_KERNEL); - if (i2400m->bm_cmd_buf == NULL) - goto error_bm_cmd_kzalloc; - i2400m->bm_ack_buf = kzalloc(I2400M_BM_ACK_BUF_SIZE, GFP_KERNEL); - if (i2400m->bm_ack_buf == NULL) - goto error_bm_ack_buf_kzalloc; - return 0; - -error_bm_ack_buf_kzalloc: - kfree(i2400m->bm_cmd_buf); -error_bm_cmd_kzalloc: - return result; -} - - -/* - * Free boot mode command and ack buffers. - */ -static -void i2400m_bm_buf_free(struct i2400m *i2400m) -{ - kfree(i2400m->bm_ack_buf); - kfree(i2400m->bm_cmd_buf); -} - - -/** - * i2400m_init - Initialize a 'struct i2400m' from all zeroes - * - * This is a bus-generic API call. - */ -void i2400m_init(struct i2400m *i2400m) -{ - wimax_dev_init(&i2400m->wimax_dev); - - i2400m->boot_mode = 1; - i2400m->rx_reorder = 1; - init_waitqueue_head(&i2400m->state_wq); - - spin_lock_init(&i2400m->tx_lock); - i2400m->tx_pl_min = UINT_MAX; - i2400m->tx_size_min = UINT_MAX; - - spin_lock_init(&i2400m->rx_lock); - i2400m->rx_pl_min = UINT_MAX; - i2400m->rx_size_min = UINT_MAX; - INIT_LIST_HEAD(&i2400m->rx_reports); - INIT_WORK(&i2400m->rx_report_ws, i2400m_report_hook_work); - - mutex_init(&i2400m->msg_mutex); - init_completion(&i2400m->msg_completion); - - mutex_init(&i2400m->init_mutex); - /* wake_tx_ws is initialized in i2400m_tx_setup() */ -} -EXPORT_SYMBOL_GPL(i2400m_init); - - -int i2400m_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) -{ - struct net_device *net_dev = i2400m->wimax_dev.net_dev; - - /* - * Make sure we stop TXs and down the carrier before - * resetting; this is needed to avoid things like - * i2400m_wake_tx() scheduling stuff in parallel. - */ - if (net_dev->reg_state == NETREG_REGISTERED) { - netif_tx_disable(net_dev); - netif_carrier_off(net_dev); - } - return i2400m->bus_reset(i2400m, rt); -} -EXPORT_SYMBOL_GPL(i2400m_reset); - - /** * i2400m_setup - bus-generic setup function for the i2400m device * @@ -840,9 +625,13 @@ EXPORT_SYMBOL_GPL(i2400m_reset); * * Returns: 0 if ok, < 0 errno code on error. * - * Sets up basic device comunication infrastructure, boots the ROM to - * read the MAC address, registers with the WiMAX and network stacks - * and then brings up the device. + * Initializes the bus-generic parts of the i2400m driver; the + * bus-specific parts have been initialized, function pointers filled + * out by the bus-specific probe function. + * + * As well, this registers the WiMAX and net device nodes. Once this + * function returns, the device is operative and has to be ready to + * receive and send network traffic and WiMAX control operations. */ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) { @@ -856,21 +645,16 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) snprintf(wimax_dev->name, sizeof(wimax_dev->name), "i2400m-%s:%s", dev->bus->name, dev_name(dev)); - result = i2400m_bm_buf_alloc(i2400m); - if (result < 0) { - dev_err(dev, "cannot allocate bootmode scratch buffers\n"); - goto error_bm_buf_alloc; + i2400m->bm_cmd_buf = kzalloc(I2400M_BM_CMD_BUF_SIZE, GFP_KERNEL); + if (i2400m->bm_cmd_buf == NULL) { + dev_err(dev, "cannot allocate USB command buffer\n"); + goto error_bm_cmd_kzalloc; } - - if (i2400m->bus_setup) { - result = i2400m->bus_setup(i2400m); - if (result < 0) { - dev_err(dev, "bus-specific setup failed: %d\n", - result); - goto error_bus_setup; - } + i2400m->bm_ack_buf = kzalloc(I2400M_BM_ACK_BUF_SIZE, GFP_KERNEL); + if (i2400m->bm_ack_buf == NULL) { + dev_err(dev, "cannot allocate USB ack buffer\n"); + goto error_bm_ack_buf_kzalloc; } - result = i2400m_bootrom_init(i2400m, bm_flags); if (result < 0) { dev_err(dev, "read mac addr: bootrom init " @@ -882,9 +666,6 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) goto error_read_mac_addr; random_ether_addr(i2400m->src_mac_addr); - i2400m->pm_notifier.notifier_call = i2400m_pm_notifier; - register_pm_notifier(&i2400m->pm_notifier); - result = register_netdev(net_dev); /* Okey dokey, bring it up */ if (result < 0) { dev_err(dev, "cannot register i2400m network device: %d\n", @@ -893,13 +674,18 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) } netif_carrier_off(net_dev); + result = i2400m_dev_start(i2400m, bm_flags); + if (result < 0) + goto error_dev_start; + i2400m->wimax_dev.op_msg_from_user = i2400m_op_msg_from_user; i2400m->wimax_dev.op_rfkill_sw_toggle = i2400m_op_rfkill_sw_toggle; i2400m->wimax_dev.op_reset = i2400m_op_reset; - result = wimax_dev_add(&i2400m->wimax_dev, net_dev); if (result < 0) goto error_wimax_dev_add; + /* User space needs to do some init stuff */ + wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED); /* Now setup all that requires a registered net and wimax device. */ result = sysfs_create_group(&net_dev->dev.kobj, &i2400m_dev_attr_group); @@ -907,37 +693,30 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) dev_err(dev, "cannot setup i2400m's sysfs: %d\n", result); goto error_sysfs_setup; } - result = i2400m_debugfs_add(i2400m); if (result < 0) { dev_err(dev, "cannot setup i2400m's debugfs: %d\n", result); goto error_debugfs_setup; } - - result = i2400m_dev_start(i2400m, bm_flags); - if (result < 0) - goto error_dev_start; d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); return result; -error_dev_start: - i2400m_debugfs_rm(i2400m); error_debugfs_setup: sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj, &i2400m_dev_attr_group); error_sysfs_setup: wimax_dev_rm(&i2400m->wimax_dev); error_wimax_dev_add: + i2400m_dev_stop(i2400m); +error_dev_start: unregister_netdev(net_dev); error_register_netdev: - unregister_pm_notifier(&i2400m->pm_notifier); error_read_mac_addr: error_bootrom_init: - if (i2400m->bus_release) - i2400m->bus_release(i2400m); -error_bus_setup: - i2400m_bm_buf_free(i2400m); -error_bm_buf_alloc: + kfree(i2400m->bm_ack_buf); +error_bm_ack_buf_kzalloc: + kfree(i2400m->bm_cmd_buf); +error_bm_cmd_kzalloc: d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); return result; } @@ -956,17 +735,14 @@ void i2400m_release(struct i2400m *i2400m) d_fnstart(3, dev, "(i2400m %p)\n", i2400m); netif_stop_queue(i2400m->wimax_dev.net_dev); - i2400m_dev_stop(i2400m); - i2400m_debugfs_rm(i2400m); sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj, &i2400m_dev_attr_group); wimax_dev_rm(&i2400m->wimax_dev); + i2400m_dev_stop(i2400m); unregister_netdev(i2400m->wimax_dev.net_dev); - unregister_pm_notifier(&i2400m->pm_notifier); - if (i2400m->bus_release) - i2400m->bus_release(i2400m); - i2400m_bm_buf_free(i2400m); + kfree(i2400m->bm_ack_buf); + kfree(i2400m->bm_cmd_buf); d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); } EXPORT_SYMBOL_GPL(i2400m_release); @@ -983,7 +759,6 @@ struct d_level D_LEVEL[] = { D_SUBMODULE_DEFINE(netdev), D_SUBMODULE_DEFINE(rfkill), D_SUBMODULE_DEFINE(rx), - D_SUBMODULE_DEFINE(sysfs), D_SUBMODULE_DEFINE(tx), }; size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); @@ -992,9 +767,7 @@ size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); static int __init i2400m_driver_init(void) { - d_parse_params(D_LEVEL, D_LEVEL_SIZE, i2400m_debug_params, - "i2400m.debug"); - return i2400m_barker_db_init(i2400m_barkers_params); + return 0; } module_init(i2400m_driver_init); @@ -1003,7 +776,6 @@ void __exit i2400m_driver_exit(void) { /* for scheds i2400m_dev_reset_handle() */ flush_scheduled_work(); - i2400m_barker_db_exit(); return; } module_exit(i2400m_driver_exit); diff --git a/trunk/drivers/net/wimax/i2400m/fw.c b/trunk/drivers/net/wimax/i2400m/fw.c index 64cdfeb299ca..e81750e54452 100644 --- a/trunk/drivers/net/wimax/i2400m/fw.c +++ b/trunk/drivers/net/wimax/i2400m/fw.c @@ -40,9 +40,11 @@ * * THE PROCEDURE * - * The 2400m and derived devices work in two modes: boot-mode or - * normal mode. In boot mode we can execute only a handful of commands - * targeted at uploading the firmware and launching it. + * (this is decribed for USB, but for SDIO is similar) + * + * The 2400m works in two modes: boot-mode or normal mode. In boot + * mode we can execute only a handful of commands targeted at + * uploading the firmware and launching it. * * The 2400m enters boot mode when it is first connected to the * system, when it crashes and when you ask it to reboot. There are @@ -50,26 +52,18 @@ * firmwares signed with a certain private key, non-signed takes any * firmware. Normal hardware takes only signed firmware. * - * On boot mode, in USB, we write to the device using the bulk out - * endpoint and read from it in the notification endpoint. In SDIO we - * talk to it via the write address and read from the read address. - * - * Upon entrance to boot mode, the device sends (preceeded with a few - * zero length packets (ZLPs) on the notification endpoint in USB) a - * reboot barker (4 le32 words with the same value). We ack it by - * sending the same barker to the device. The device acks with a - * reboot ack barker (4 le32 words with value I2400M_ACK_BARKER) and - * then is fully booted. At this point we can upload the firmware. - * - * Note that different iterations of the device and EEPROM - * configurations will send different [re]boot barkers; these are - * collected in i2400m_barker_db along with the firmware - * characteristics they require. + * Upon entrance to boot mode, the device sends a few zero length + * packets (ZLPs) on the notification endpoint, then a reboot barker + * (4 le32 words with value I2400M_{S,N}BOOT_BARKER). We ack it by + * sending the same barker on the bulk out endpoint. The device acks + * with a reboot ack barker (4 le32 words with value 0xfeedbabe) and + * then the device is fully rebooted. At this point we can upload the + * firmware. * * This process is accomplished by the i2400m_bootrom_init() * function. All the device interaction happens through the * i2400m_bm_cmd() [boot mode command]. Special return values will - * indicate if the device did reset during the process. + * indicate if the device resets. * * After this, we read the MAC address and then (if needed) * reinitialize the device. We need to read it ahead of time because @@ -78,11 +72,11 @@ * * We can then upload the firmware file. The file is composed of a BCF * header (basic data, keys and signatures) and a list of write - * commands and payloads. Optionally more BCF headers might follow the - * main payload. We first upload the header [i2400m_dnload_init()] and - * then pass the commands and payloads verbatim to the i2400m_bm_cmd() - * function [i2400m_dnload_bcf()]. Then we tell the device to jump to - * the new firmware [i2400m_dnload_finalize()]. + * commands and payloads. We first upload the header + * [i2400m_dnload_init()] and then pass the commands and payloads + * verbatim to the i2400m_bm_cmd() function + * [i2400m_dnload_bcf()]. Then we tell the device to jump to the new + * firmware [i2400m_dnload_finalize()]. * * Once firmware is uploaded, we are good to go :) * @@ -105,32 +99,18 @@ * read an acknolwedgement from it (or an asynchronous notification) * from it. * - * FIRMWARE LOADING - * - * Note that in some cases, we can't just load a firmware file (for - * example, when resuming). For that, we might cache the firmware - * file. Thus, when doing the bootstrap, if there is a cache firmware - * file, it is used; if not, loading from disk is attempted. - * * ROADMAP * - * i2400m_barker_db_init Called by i2400m_driver_init() - * i2400m_barker_db_add - * - * i2400m_barker_db_exit Called by i2400m_driver_exit() - * * i2400m_dev_bootstrap Called by __i2400m_dev_start() * request_firmware - * i2400m_fw_bootstrap - * i2400m_fw_check - * i2400m_fw_hdr_check - * i2400m_fw_dnload + * i2400m_fw_check + * i2400m_fw_dnload * release_firmware * * i2400m_fw_dnload * i2400m_bootrom_init * i2400m_bm_cmd - * i2400m_reset + * i2400m->bus_reset * i2400m_dnload_init * i2400m_dnload_init_signed * i2400m_dnload_init_nonsigned @@ -145,14 +125,9 @@ * i2400m->bus_bm_cmd_send() * i2400m->bus_bm_wait_for_ack * __i2400m_bm_ack_verify - * i2400m_is_boot_barker * * i2400m_bm_cmd_prepare Used by bus-drivers to prep * commands before sending - * - * i2400m_pm_notifier Called on Power Management events - * i2400m_fw_cache - * i2400m_fw_uncache */ #include #include @@ -199,240 +174,6 @@ void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *cmd) EXPORT_SYMBOL_GPL(i2400m_bm_cmd_prepare); -/* - * Database of known barkers. - * - * A barker is what the device sends indicating he is ready to be - * bootloaded. Different versions of the device will send different - * barkers. Depending on the barker, it might mean the device wants - * some kind of firmware or the other. - */ -static struct i2400m_barker_db { - __le32 data[4]; -} *i2400m_barker_db; -static size_t i2400m_barker_db_used, i2400m_barker_db_size; - - -static -int i2400m_zrealloc_2x(void **ptr, size_t *_count, size_t el_size, - gfp_t gfp_flags) -{ - size_t old_count = *_count, - new_count = old_count ? 2 * old_count : 2, - old_size = el_size * old_count, - new_size = el_size * new_count; - void *nptr = krealloc(*ptr, new_size, gfp_flags); - if (nptr) { - /* zero the other half or the whole thing if old_count - * was zero */ - if (old_size == 0) - memset(nptr, 0, new_size); - else - memset(nptr + old_size, 0, old_size); - *_count = new_count; - *ptr = nptr; - return 0; - } else - return -ENOMEM; -} - - -/* - * Add a barker to the database - * - * This cannot used outside of this module and only at at module_init - * time. This is to avoid the need to do locking. - */ -static -int i2400m_barker_db_add(u32 barker_id) -{ - int result; - - struct i2400m_barker_db *barker; - if (i2400m_barker_db_used >= i2400m_barker_db_size) { - result = i2400m_zrealloc_2x( - (void **) &i2400m_barker_db, &i2400m_barker_db_size, - sizeof(i2400m_barker_db[0]), GFP_KERNEL); - if (result < 0) - return result; - } - barker = i2400m_barker_db + i2400m_barker_db_used++; - barker->data[0] = le32_to_cpu(barker_id); - barker->data[1] = le32_to_cpu(barker_id); - barker->data[2] = le32_to_cpu(barker_id); - barker->data[3] = le32_to_cpu(barker_id); - return 0; -} - - -void i2400m_barker_db_exit(void) -{ - kfree(i2400m_barker_db); - i2400m_barker_db = NULL; - i2400m_barker_db_size = 0; - i2400m_barker_db_used = 0; -} - - -/* - * Helper function to add all the known stable barkers to the barker - * database. - */ -static -int i2400m_barker_db_known_barkers(void) -{ - int result; - - result = i2400m_barker_db_add(I2400M_NBOOT_BARKER); - if (result < 0) - goto error_add; - result = i2400m_barker_db_add(I2400M_SBOOT_BARKER); - if (result < 0) - goto error_add; - result = i2400m_barker_db_add(I2400M_SBOOT_BARKER_6050); - if (result < 0) - goto error_add; -error_add: - return result; -} - - -/* - * Initialize the barker database - * - * This can only be used from the module_init function for this - * module; this is to avoid the need to do locking. - * - * @options: command line argument with extra barkers to - * recognize. This is a comma-separated list of 32-bit hex - * numbers. They are appended to the existing list. Setting 0 - * cleans the existing list and starts a new one. - */ -int i2400m_barker_db_init(const char *_options) -{ - int result; - char *options = NULL, *options_orig, *token; - - i2400m_barker_db = NULL; - i2400m_barker_db_size = 0; - i2400m_barker_db_used = 0; - - result = i2400m_barker_db_known_barkers(); - if (result < 0) - goto error_add; - /* parse command line options from i2400m.barkers */ - if (_options != NULL) { - unsigned barker; - - options_orig = kstrdup(_options, GFP_KERNEL); - if (options_orig == NULL) - goto error_parse; - options = options_orig; - - while ((token = strsep(&options, ",")) != NULL) { - if (*token == '\0') /* eat joint commas */ - continue; - if (sscanf(token, "%x", &barker) != 1 - || barker > 0xffffffff) { - printk(KERN_ERR "%s: can't recognize " - "i2400m.barkers value '%s' as " - "a 32-bit number\n", - __func__, token); - result = -EINVAL; - goto error_parse; - } - if (barker == 0) { - /* clean list and start new */ - i2400m_barker_db_exit(); - continue; - } - result = i2400m_barker_db_add(barker); - if (result < 0) - goto error_add; - } - kfree(options_orig); - } - return 0; - -error_parse: -error_add: - kfree(i2400m_barker_db); - return result; -} - - -/* - * Recognize a boot barker - * - * @buf: buffer where the boot barker. - * @buf_size: size of the buffer (has to be 16 bytes). It is passed - * here so the function can check it for the caller. - * - * Note that as a side effect, upon identifying the obtained boot - * barker, this function will set i2400m->barker to point to the right - * barker database entry. Subsequent calls to the function will result - * in verifying that the same type of boot barker is returned when the - * device [re]boots (as long as the same device instance is used). - * - * Return: 0 if @buf matches a known boot barker. -ENOENT if the - * buffer in @buf doesn't match any boot barker in the database or - * -EILSEQ if the buffer doesn't have the right size. - */ -int i2400m_is_boot_barker(struct i2400m *i2400m, - const void *buf, size_t buf_size) -{ - int result; - struct device *dev = i2400m_dev(i2400m); - struct i2400m_barker_db *barker; - int i; - - result = -ENOENT; - if (buf_size != sizeof(i2400m_barker_db[i].data)) - return result; - - /* Short circuit if we have already discovered the barker - * associated with the device. */ - if (i2400m->barker - && !memcmp(buf, i2400m->barker, sizeof(i2400m->barker->data))) { - unsigned index = (i2400m->barker - i2400m_barker_db) - / sizeof(*i2400m->barker); - d_printf(2, dev, "boot barker cache-confirmed #%u/%08x\n", - index, le32_to_cpu(i2400m->barker->data[0])); - return 0; - } - - for (i = 0; i < i2400m_barker_db_used; i++) { - barker = &i2400m_barker_db[i]; - BUILD_BUG_ON(sizeof(barker->data) != 16); - if (memcmp(buf, barker->data, sizeof(barker->data))) - continue; - - if (i2400m->barker == NULL) { - i2400m->barker = barker; - d_printf(1, dev, "boot barker set to #%u/%08x\n", - i, le32_to_cpu(barker->data[0])); - if (barker->data[0] == le32_to_cpu(I2400M_NBOOT_BARKER)) - i2400m->sboot = 0; - else - i2400m->sboot = 1; - } else if (i2400m->barker != barker) { - dev_err(dev, "HW inconsistency: device " - "reports a different boot barker " - "than set (from %08x to %08x)\n", - le32_to_cpu(i2400m->barker->data[0]), - le32_to_cpu(barker->data[0])); - result = -EIO; - } else - d_printf(2, dev, "boot barker confirmed #%u/%08x\n", - i, le32_to_cpu(barker->data[0])); - result = 0; - break; - } - return result; -} -EXPORT_SYMBOL_GPL(i2400m_is_boot_barker); - - /* * Verify the ack data received * @@ -463,10 +204,20 @@ ssize_t __i2400m_bm_ack_verify(struct i2400m *i2400m, int opcode, opcode, ack_size, sizeof(*ack)); goto error_ack_short; } - result = i2400m_is_boot_barker(i2400m, ack, ack_size); - if (result >= 0) { + if (ack_size == sizeof(i2400m_NBOOT_BARKER) + && memcmp(ack, i2400m_NBOOT_BARKER, sizeof(*ack)) == 0) { result = -ERESTARTSYS; - d_printf(6, dev, "boot-mode cmd %d: HW boot barker\n", opcode); + i2400m->sboot = 0; + d_printf(6, dev, "boot-mode cmd %d: " + "HW non-signed boot barker\n", opcode); + goto error_reboot; + } + if (ack_size == sizeof(i2400m_SBOOT_BARKER) + && memcmp(ack, i2400m_SBOOT_BARKER, sizeof(*ack)) == 0) { + result = -ERESTARTSYS; + i2400m->sboot = 1; + d_printf(6, dev, "boot-mode cmd %d: HW signed reboot barker\n", + opcode); goto error_reboot; } if (ack_size == sizeof(i2400m_ACK_BARKER) @@ -592,6 +343,7 @@ ssize_t i2400m_bm_cmd(struct i2400m *i2400m, BUG_ON(i2400m->boot_mode == 0); if (cmd != NULL) { /* send the command */ + memcpy(i2400m->bm_cmd_buf, cmd, cmd_size); result = i2400m->bus_bm_cmd_send(i2400m, cmd, cmd_size, flags); if (result < 0) goto error_cmd_send; @@ -680,8 +432,8 @@ static int i2400m_download_chunk(struct i2400m *i2400m, const void *chunk, * Download a BCF file's sections to the device * * @i2400m: device descriptor - * @bcf: pointer to firmware data (first header followed by the - * payloads). Assumed verified and consistent. + * @bcf: pointer to firmware data (followed by the payloads). Assumed + * verified and consistent. * @bcf_len: length (in bytes) of the @bcf buffer. * * Returns: < 0 errno code on error or the offset to the jump instruction. @@ -720,17 +472,14 @@ ssize_t i2400m_dnload_bcf(struct i2400m *i2400m, "downloading section #%zu (@%zu %zu B) to 0x%08x\n", section, offset, sizeof(*bh) + data_size, le32_to_cpu(bh->target_addr)); - /* - * We look for JUMP cmd from the bootmode header, - * either I2400M_BRH_SIGNED_JUMP for secure boot - * or I2400M_BRH_JUMP for unsecure boot, the last chunk - * should be the bootmode header with JUMP cmd. - */ - if (i2400m_brh_get_opcode(bh) == I2400M_BRH_SIGNED_JUMP || - i2400m_brh_get_opcode(bh) == I2400M_BRH_JUMP) { - d_printf(5, dev, "jump found @%zu\n", offset); + if (i2400m_brh_get_opcode(bh) == I2400M_BRH_SIGNED_JUMP) { + /* Secure boot needs to stop here */ + d_printf(5, dev, "signed jump found @%zu\n", offset); break; } + if (offset + section_size == bcf_len) + /* Non-secure boot stops here */ + break; if (offset + section_size > bcf_len) { dev_err(dev, "fw %s: bad section #%zu, " "end (@%zu) beyond EOF (@%zu)\n", @@ -760,31 +509,14 @@ ssize_t i2400m_dnload_bcf(struct i2400m *i2400m, } -/* - * Indicate if the device emitted a reboot barker that indicates - * "signed boot" - */ -static -unsigned i2400m_boot_is_signed(struct i2400m *i2400m) -{ - return likely(i2400m->sboot); -} - - /* * Do the final steps of uploading firmware * - * @bcf_hdr: BCF header we are actually using - * @bcf: pointer to the firmware image (which matches the first header - * that is followed by the actual payloads). - * @offset: [byte] offset into @bcf for the command we need to send. - * * Depending on the boot mode (signed vs non-signed), different * actions need to be taken. */ static int i2400m_dnload_finalize(struct i2400m *i2400m, - const struct i2400m_bcf_hdr *bcf_hdr, const struct i2400m_bcf_hdr *bcf, size_t offset) { int ret = 0; @@ -798,14 +530,10 @@ int i2400m_dnload_finalize(struct i2400m *i2400m, d_fnstart(3, dev, "offset %zu\n", offset); cmd = (void *) bcf + offset; - if (i2400m_boot_is_signed(i2400m) == 0) { + if (i2400m->sboot == 0) { struct i2400m_bootrom_header jump_ack; d_printf(1, dev, "unsecure boot, jumping to 0x%08x\n", le32_to_cpu(cmd->target_addr)); - cmd_buf = i2400m->bm_cmd_buf; - memcpy(&cmd_buf->cmd, cmd, sizeof(*cmd)); - cmd = &cmd_buf->cmd; - /* now cmd points to the actual bootrom_header in cmd_buf */ i2400m_brh_set_opcode(cmd, I2400M_BRH_JUMP); cmd->data_size = 0; ret = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd), @@ -816,13 +544,12 @@ int i2400m_dnload_finalize(struct i2400m *i2400m, cmd_buf = i2400m->bm_cmd_buf; memcpy(&cmd_buf->cmd, cmd, sizeof(*cmd)); signature_block_offset = - sizeof(*bcf_hdr) - + le32_to_cpu(bcf_hdr->key_size) * sizeof(u32) - + le32_to_cpu(bcf_hdr->exponent_size) * sizeof(u32); + sizeof(*bcf) + + le32_to_cpu(bcf->key_size) * sizeof(u32) + + le32_to_cpu(bcf->exponent_size) * sizeof(u32); signature_block_size = - le32_to_cpu(bcf_hdr->modulus_size) * sizeof(u32); - memcpy(cmd_buf->cmd_pl, - (void *) bcf_hdr + signature_block_offset, + le32_to_cpu(bcf->modulus_size) * sizeof(u32); + memcpy(cmd_buf->cmd_pl, (void *) bcf + signature_block_offset, signature_block_size); ret = i2400m_bm_cmd(i2400m, &cmd_buf->cmd, sizeof(cmd_buf->cmd) + signature_block_size, @@ -838,7 +565,7 @@ int i2400m_dnload_finalize(struct i2400m *i2400m, * * @i2400m: device descriptor * @flags: - * I2400M_BRI_SOFT: a reboot barker has been seen + * I2400M_BRI_SOFT: a reboot notification has been seen * already, so don't wait for it. * * I2400M_BRI_NO_REBOOT: Don't send a reboot command, but wait @@ -849,15 +576,17 @@ int i2400m_dnload_finalize(struct i2400m *i2400m, * * < 0 errno code on error, 0 if ok. * + * i2400m->sboot set to 0 for unsecure boot process, 1 for secure + * boot process. + * * Description: * * Tries hard enough to put the device in boot-mode. There are two * main phases to this: * * a. (1) send a reboot command and (2) get a reboot barker - * - * b. (1) echo/ack the reboot sending the reboot barker back and (2) - * getting an ack barker in return + * b. (1) ack the reboot sending a reboot barker and (2) getting an + * ack barker in return * * We want to skip (a) in some cases [soft]. The state machine is * horrible, but it is basically: on each phase, send what has to be @@ -865,16 +594,6 @@ int i2400m_dnload_finalize(struct i2400m *i2400m, * have to backtrack and retry, so we keep a max tries counter for * that. * - * It sucks because we don't know ahead of time which is going to be - * the reboot barker (the device might send different ones depending - * on its EEPROM config) and once the device reboots and waits for the - * echo/ack reboot barker being sent back, it doesn't understand - * anything else. So we can be left at the point where we don't know - * what to send to it -- cold reset and bus reset seem to have little - * effect. So the function iterates (in this case) through all the - * known barkers and tries them all until an ACK is - * received. Otherwise, it gives up. - * * If we get a timeout after sending a warm reset, we do it again. */ int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags) @@ -883,11 +602,10 @@ int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags) struct device *dev = i2400m_dev(i2400m); struct i2400m_bootrom_header *cmd; struct i2400m_bootrom_header ack; - int count = i2400m->bus_bm_retries; + int count = I2400M_BOOT_RETRIES; int ack_timeout_cnt = 1; - unsigned i; - BUILD_BUG_ON(sizeof(*cmd) != sizeof(i2400m_barker_db[0].data)); + BUILD_BUG_ON(sizeof(*cmd) != sizeof(i2400m_NBOOT_BARKER)); BUILD_BUG_ON(sizeof(ack) != sizeof(i2400m_ACK_BARKER)); d_fnstart(4, dev, "(i2400m %p flags 0x%08x)\n", i2400m, flags); @@ -896,59 +614,27 @@ int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags) if (flags & I2400M_BRI_SOFT) goto do_reboot_ack; do_reboot: - ack_timeout_cnt = 1; if (--count < 0) goto error_timeout; d_printf(4, dev, "device reboot: reboot command [%d # left]\n", count); if ((flags & I2400M_BRI_NO_REBOOT) == 0) - i2400m_reset(i2400m, I2400M_RT_WARM); + i2400m->bus_reset(i2400m, I2400M_RT_WARM); result = i2400m_bm_cmd(i2400m, NULL, 0, &ack, sizeof(ack), I2400M_BM_CMD_RAW); flags &= ~I2400M_BRI_NO_REBOOT; switch (result) { case -ERESTARTSYS: - /* - * at this point, i2400m_bm_cmd(), through - * __i2400m_bm_ack_process(), has updated - * i2400m->barker and we are good to go. - */ d_printf(4, dev, "device reboot: got reboot barker\n"); break; case -EISCONN: /* we don't know how it got here...but we follow it */ d_printf(4, dev, "device reboot: got ack barker - whatever\n"); goto do_reboot; - case -ETIMEDOUT: - /* - * Device has timed out, we might be in boot mode - * already and expecting an ack; if we don't know what - * the barker is, we just send them all. Cold reset - * and bus reset don't work. Beats me. - */ - if (i2400m->barker != NULL) { - dev_err(dev, "device boot: reboot barker timed out, " - "trying (set) %08x echo/ack\n", - le32_to_cpu(i2400m->barker->data[0])); - goto do_reboot_ack; - } - for (i = 0; i < i2400m_barker_db_used; i++) { - struct i2400m_barker_db *barker = &i2400m_barker_db[i]; - memcpy(cmd, barker->data, sizeof(barker->data)); - result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd), - &ack, sizeof(ack), - I2400M_BM_CMD_RAW); - if (result == -EISCONN) { - dev_warn(dev, "device boot: got ack barker " - "after sending echo/ack barker " - "#%d/%08x; rebooting j.i.c.\n", - i, le32_to_cpu(barker->data[0])); - flags &= ~I2400M_BRI_NO_REBOOT; - goto do_reboot; - } - } - dev_err(dev, "device boot: tried all the echo/acks, could " - "not get device to respond; giving up"); - result = -ESHUTDOWN; + case -ETIMEDOUT: /* device has timed out, we might be in boot + * mode already and expecting an ack, let's try + * that */ + dev_info(dev, "warm reset timed out, trying an ack\n"); + goto do_reboot_ack; case -EPROTO: case -ESHUTDOWN: /* dev is gone */ case -EINTR: /* user cancelled */ @@ -956,7 +642,6 @@ int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags) default: dev_err(dev, "device reboot: error %d while waiting " "for reboot barker - rebooting\n", result); - d_dump(1, dev, &ack, result); goto do_reboot; } /* At this point we ack back with 4 REBOOT barkers and expect @@ -965,7 +650,12 @@ int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags) * notification and report it as -EISCONN. */ do_reboot_ack: d_printf(4, dev, "device reboot ack: sending ack [%d # left]\n", count); - memcpy(cmd, i2400m->barker->data, sizeof(i2400m->barker->data)); + if (i2400m->sboot == 0) + memcpy(cmd, i2400m_NBOOT_BARKER, + sizeof(i2400m_NBOOT_BARKER)); + else + memcpy(cmd, i2400m_SBOOT_BARKER, + sizeof(i2400m_SBOOT_BARKER)); result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd), &ack, sizeof(ack), I2400M_BM_CMD_RAW); switch (result) { @@ -978,8 +668,10 @@ int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags) d_printf(4, dev, "reboot ack: got ack barker - good\n"); break; case -ETIMEDOUT: /* no response, maybe it is the other type? */ - if (ack_timeout_cnt-- < 0) { - d_printf(4, dev, "reboot ack timedout: retrying\n"); + if (ack_timeout_cnt-- >= 0) { + d_printf(4, dev, "reboot ack timedout: " + "trying the other type?\n"); + i2400m->sboot = !i2400m->sboot; goto do_reboot_ack; } else { dev_err(dev, "reboot ack timedout too long: " @@ -1147,29 +839,32 @@ int i2400m_dnload_init_signed(struct i2400m *i2400m, * (signed or non-signed). */ static -int i2400m_dnload_init(struct i2400m *i2400m, - const struct i2400m_bcf_hdr *bcf_hdr) +int i2400m_dnload_init(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf) { int result; struct device *dev = i2400m_dev(i2400m); + u32 module_id = le32_to_cpu(bcf->module_id); - if (i2400m_boot_is_signed(i2400m)) { - d_printf(1, dev, "signed boot\n"); - result = i2400m_dnload_init_signed(i2400m, bcf_hdr); + if (i2400m->sboot == 0 + && (module_id & I2400M_BCF_MOD_ID_POKES) == 0) { + /* non-signed boot process without pokes */ + result = i2400m_dnload_init_nonsigned(i2400m); if (result == -ERESTARTSYS) return result; if (result < 0) - dev_err(dev, "firmware %s: signed boot download " + dev_err(dev, "fw %s: non-signed download " "initialization failed: %d\n", i2400m->fw_name, result); - } else { - /* non-signed boot process without pokes */ - d_printf(1, dev, "non-signed boot\n"); - result = i2400m_dnload_init_nonsigned(i2400m); + } else if (i2400m->sboot == 0 + && (module_id & I2400M_BCF_MOD_ID_POKES)) { + /* non-signed boot process with pokes, nothing to do */ + result = 0; + } else { /* signed boot process */ + result = i2400m_dnload_init_signed(i2400m, bcf); if (result == -ERESTARTSYS) return result; if (result < 0) - dev_err(dev, "firmware %s: non-signed download " + dev_err(dev, "fw %s: signed boot download " "initialization failed: %d\n", i2400m->fw_name, result); } @@ -1178,200 +873,73 @@ int i2400m_dnload_init(struct i2400m *i2400m, /* - * Run consistency tests on the firmware file and load up headers + * Run quick consistency tests on the firmware file * * Check for the firmware being made for the i2400m device, * etc...These checks are mostly informative, as the device will make * them too; but the driver's response is more informative on what * went wrong. - * - * This will also look at all the headers present on the firmware - * file, and update i2400m->fw_bcf_hdr to point to them. */ static -int i2400m_fw_hdr_check(struct i2400m *i2400m, - const struct i2400m_bcf_hdr *bcf_hdr, - size_t index, size_t offset) +int i2400m_fw_check(struct i2400m *i2400m, + const struct i2400m_bcf_hdr *bcf, + size_t bcf_size) { + int result; struct device *dev = i2400m_dev(i2400m); - unsigned module_type, header_len, major_version, minor_version, module_id, module_vendor, date, size; - module_type = bcf_hdr->module_type; - header_len = sizeof(u32) * le32_to_cpu(bcf_hdr->header_len); - major_version = (le32_to_cpu(bcf_hdr->header_version) & 0xffff0000) - >> 16; - minor_version = le32_to_cpu(bcf_hdr->header_version) & 0x0000ffff; - module_id = le32_to_cpu(bcf_hdr->module_id); - module_vendor = le32_to_cpu(bcf_hdr->module_vendor); - date = le32_to_cpu(bcf_hdr->date); - size = sizeof(u32) * le32_to_cpu(bcf_hdr->size); - - d_printf(1, dev, "firmware %s #%zd@%08zx: BCF header " - "type:vendor:id 0x%x:%x:%x v%u.%u (%u/%u B) built %08x\n", - i2400m->fw_name, index, offset, - module_type, module_vendor, module_id, - major_version, minor_version, header_len, size, date); - - /* Hard errors */ - if (major_version != 1) { - dev_err(dev, "firmware %s #%zd@%08zx: major header version " - "v%u.%u not supported\n", - i2400m->fw_name, index, offset, - major_version, minor_version); - return -EBADF; + /* Check hard errors */ + result = -EINVAL; + if (bcf_size < sizeof(*bcf)) { /* big enough header? */ + dev_err(dev, "firmware %s too short: " + "%zu B vs %zu (at least) expected\n", + i2400m->fw_name, bcf_size, sizeof(*bcf)); + goto error; } - if (module_type != 6) { /* built for the right hardware? */ - dev_err(dev, "firmware %s #%zd@%08zx: unexpected module " - "type 0x%x; aborting\n", - i2400m->fw_name, index, offset, - module_type); - return -EBADF; + module_type = bcf->module_type; + header_len = sizeof(u32) * le32_to_cpu(bcf->header_len); + major_version = le32_to_cpu(bcf->header_version) & 0xffff0000 >> 16; + minor_version = le32_to_cpu(bcf->header_version) & 0x0000ffff; + module_id = le32_to_cpu(bcf->module_id); + module_vendor = le32_to_cpu(bcf->module_vendor); + date = le32_to_cpu(bcf->date); + size = sizeof(u32) * le32_to_cpu(bcf->size); + + if (bcf_size != size) { /* annoyingly paranoid */ + dev_err(dev, "firmware %s: bad size, got " + "%zu B vs %u expected\n", + i2400m->fw_name, bcf_size, size); + goto error; } - if (module_vendor != 0x8086) { - dev_err(dev, "firmware %s #%zd@%08zx: unexpected module " - "vendor 0x%x; aborting\n", - i2400m->fw_name, index, offset, module_vendor); - return -EBADF; + d_printf(2, dev, "type 0x%x id 0x%x vendor 0x%x; header v%u.%u (%zu B) " + "date %08x (%zu B)\n", + module_type, module_id, module_vendor, + major_version, minor_version, (size_t) header_len, + date, (size_t) size); + + if (module_type != 6) { /* built for the right hardware? */ + dev_err(dev, "bad fw %s: unexpected module type 0x%x; " + "aborting\n", i2400m->fw_name, module_type); + goto error; } + /* Check soft-er errors */ + result = 0; + if (module_vendor != 0x8086) + dev_err(dev, "bad fw %s? unexpected vendor 0x%04x\n", + i2400m->fw_name, module_vendor); if (date < 0x20080300) - dev_warn(dev, "firmware %s #%zd@%08zx: build date %08x " - "too old; unsupported\n", - i2400m->fw_name, index, offset, date); - return 0; -} - - -/* - * Run consistency tests on the firmware file and load up headers - * - * Check for the firmware being made for the i2400m device, - * etc...These checks are mostly informative, as the device will make - * them too; but the driver's response is more informative on what - * went wrong. - * - * This will also look at all the headers present on the firmware - * file, and update i2400m->fw_hdrs to point to them. - */ -static -int i2400m_fw_check(struct i2400m *i2400m, const void *bcf, size_t bcf_size) -{ - int result; - struct device *dev = i2400m_dev(i2400m); - size_t headers = 0; - const struct i2400m_bcf_hdr *bcf_hdr; - const void *itr, *next, *top; - size_t slots = 0, used_slots = 0; - - for (itr = bcf, top = itr + bcf_size; - itr < top; - headers++, itr = next) { - size_t leftover, offset, header_len, size; - - leftover = top - itr; - offset = itr - (const void *) bcf; - if (leftover <= sizeof(*bcf_hdr)) { - dev_err(dev, "firmware %s: %zu B left at @%zx, " - "not enough for BCF header\n", - i2400m->fw_name, leftover, offset); - break; - } - bcf_hdr = itr; - /* Only the first header is supposed to be followed by - * payload */ - header_len = sizeof(u32) * le32_to_cpu(bcf_hdr->header_len); - size = sizeof(u32) * le32_to_cpu(bcf_hdr->size); - if (headers == 0) - next = itr + size; - else - next = itr + header_len; - - result = i2400m_fw_hdr_check(i2400m, bcf_hdr, headers, offset); - if (result < 0) - continue; - if (used_slots + 1 >= slots) { - /* +1 -> we need to account for the one we'll - * occupy and at least an extra one for - * always being NULL */ - result = i2400m_zrealloc_2x( - (void **) &i2400m->fw_hdrs, &slots, - sizeof(i2400m->fw_hdrs[0]), - GFP_KERNEL); - if (result < 0) - goto error_zrealloc; - } - i2400m->fw_hdrs[used_slots] = bcf_hdr; - used_slots++; - } - if (headers == 0) { - dev_err(dev, "firmware %s: no usable headers found\n", - i2400m->fw_name); - result = -EBADF; - } else - result = 0; -error_zrealloc: + dev_err(dev, "bad fw %s? build date too old %08x\n", + i2400m->fw_name, date); +error: return result; } -/* - * Match a barker to a BCF header module ID - * - * The device sends a barker which tells the firmware loader which - * header in the BCF file has to be used. This does the matching. - */ -static -unsigned i2400m_bcf_hdr_match(struct i2400m *i2400m, - const struct i2400m_bcf_hdr *bcf_hdr) -{ - u32 barker = le32_to_cpu(i2400m->barker->data[0]) - & 0x7fffffff; - u32 module_id = le32_to_cpu(bcf_hdr->module_id) - & 0x7fffffff; /* high bit used for something else */ - - /* special case for 5x50 */ - if (barker == I2400M_SBOOT_BARKER && module_id == 0) - return 1; - if (module_id == barker) - return 1; - return 0; -} - -static -const struct i2400m_bcf_hdr *i2400m_bcf_hdr_find(struct i2400m *i2400m) -{ - struct device *dev = i2400m_dev(i2400m); - const struct i2400m_bcf_hdr **bcf_itr, *bcf_hdr; - unsigned i = 0; - u32 barker = le32_to_cpu(i2400m->barker->data[0]); - - d_printf(2, dev, "finding BCF header for barker %08x\n", barker); - if (barker == I2400M_NBOOT_BARKER) { - bcf_hdr = i2400m->fw_hdrs[0]; - d_printf(1, dev, "using BCF header #%u/%08x for non-signed " - "barker\n", 0, le32_to_cpu(bcf_hdr->module_id)); - return bcf_hdr; - } - for (bcf_itr = i2400m->fw_hdrs; *bcf_itr != NULL; bcf_itr++, i++) { - bcf_hdr = *bcf_itr; - if (i2400m_bcf_hdr_match(i2400m, bcf_hdr)) { - d_printf(1, dev, "hit on BCF hdr #%u/%08x\n", - i, le32_to_cpu(bcf_hdr->module_id)); - return bcf_hdr; - } else - d_printf(1, dev, "miss on BCF hdr #%u/%08x\n", - i, le32_to_cpu(bcf_hdr->module_id)); - } - dev_err(dev, "cannot find a matching BCF header for barker %08x\n", - barker); - return NULL; -} - - /* * Download the firmware to the device * @@ -1388,16 +956,14 @@ const struct i2400m_bcf_hdr *i2400m_bcf_hdr_find(struct i2400m *i2400m) */ static int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf, - size_t fw_size, enum i2400m_bri flags) + size_t bcf_size, enum i2400m_bri flags) { int ret = 0; struct device *dev = i2400m_dev(i2400m); int count = i2400m->bus_bm_retries; - const struct i2400m_bcf_hdr *bcf_hdr; - size_t bcf_size; - d_fnstart(5, dev, "(i2400m %p bcf %p fw size %zu)\n", - i2400m, bcf, fw_size); + d_fnstart(5, dev, "(i2400m %p bcf %p size %zu)\n", + i2400m, bcf, bcf_size); i2400m->boot_mode = 1; wmb(); /* Make sure other readers see it */ hw_reboot: @@ -1419,28 +985,13 @@ int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf, * Initialize the download, push the bytes to the device and * then jump to the new firmware. Note @ret is passed with the * offset of the jump instruction to _dnload_finalize() - * - * Note we need to use the BCF header in the firmware image - * that matches the barker that the device sent when it - * rebooted, so it has to be passed along. */ - ret = -EBADF; - bcf_hdr = i2400m_bcf_hdr_find(i2400m); - if (bcf_hdr == NULL) - goto error_bcf_hdr_find; - - ret = i2400m_dnload_init(i2400m, bcf_hdr); + ret = i2400m_dnload_init(i2400m, bcf); /* Init device's dnload */ if (ret == -ERESTARTSYS) goto error_dev_rebooted; if (ret < 0) goto error_dnload_init; - /* - * bcf_size refers to one header size plus the fw sections size - * indicated by the header,ie. if there are other extended headers - * at the tail, they are not counted - */ - bcf_size = sizeof(u32) * le32_to_cpu(bcf_hdr->size); ret = i2400m_dnload_bcf(i2400m, bcf, bcf_size); if (ret == -ERESTARTSYS) goto error_dev_rebooted; @@ -1450,7 +1001,7 @@ int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf, goto error_dnload_bcf; } - ret = i2400m_dnload_finalize(i2400m, bcf_hdr, bcf, ret); + ret = i2400m_dnload_finalize(i2400m, bcf, ret); if (ret == -ERESTARTSYS) goto error_dev_rebooted; if (ret < 0) { @@ -1467,11 +1018,10 @@ int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf, error_dnload_finalize: error_dnload_bcf: error_dnload_init: -error_bcf_hdr_find: error_bootrom_init: error_too_many_reboots: d_fnend(5, dev, "(i2400m %p bcf %p size %zu) = %d\n", - i2400m, bcf, fw_size, ret); + i2400m, bcf, bcf_size, ret); return ret; error_dev_rebooted: @@ -1481,61 +1031,6 @@ int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf, goto hw_reboot; } -static -int i2400m_fw_bootstrap(struct i2400m *i2400m, const struct firmware *fw, - enum i2400m_bri flags) -{ - int ret; - struct device *dev = i2400m_dev(i2400m); - const struct i2400m_bcf_hdr *bcf; /* Firmware data */ - - d_fnstart(5, dev, "(i2400m %p)\n", i2400m); - bcf = (void *) fw->data; - ret = i2400m_fw_check(i2400m, bcf, fw->size); - if (ret >= 0) - ret = i2400m_fw_dnload(i2400m, bcf, fw->size, flags); - if (ret < 0) - dev_err(dev, "%s: cannot use: %d, skipping\n", - i2400m->fw_name, ret); - kfree(i2400m->fw_hdrs); - i2400m->fw_hdrs = NULL; - d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret); - return ret; -} - - -/* Refcounted container for firmware data */ -struct i2400m_fw { - struct kref kref; - const struct firmware *fw; -}; - - -static -void i2400m_fw_destroy(struct kref *kref) -{ - struct i2400m_fw *i2400m_fw = - container_of(kref, struct i2400m_fw, kref); - release_firmware(i2400m_fw->fw); - kfree(i2400m_fw); -} - - -static -struct i2400m_fw *i2400m_fw_get(struct i2400m_fw *i2400m_fw) -{ - if (i2400m_fw != NULL && i2400m_fw != (void *) ~0) - kref_get(&i2400m_fw->kref); - return i2400m_fw; -} - - -static -void i2400m_fw_put(struct i2400m_fw *i2400m_fw) -{ - kref_put(&i2400m_fw->kref, i2400m_fw_destroy); -} - /** * i2400m_dev_bootstrap - Bring the device to a known state and upload firmware @@ -1554,109 +1049,42 @@ void i2400m_fw_put(struct i2400m_fw *i2400m_fw) */ int i2400m_dev_bootstrap(struct i2400m *i2400m, enum i2400m_bri flags) { - int ret, itr; + int ret = 0, itr = 0; struct device *dev = i2400m_dev(i2400m); - struct i2400m_fw *i2400m_fw; - const struct i2400m_bcf_hdr *bcf; /* Firmware data */ const struct firmware *fw; + const struct i2400m_bcf_hdr *bcf; /* Firmware data */ const char *fw_name; d_fnstart(5, dev, "(i2400m %p)\n", i2400m); - ret = -ENODEV; - spin_lock(&i2400m->rx_lock); - i2400m_fw = i2400m_fw_get(i2400m->fw_cached); - spin_unlock(&i2400m->rx_lock); - if (i2400m_fw == (void *) ~0) { - dev_err(dev, "can't load firmware now!"); - goto out; - } else if (i2400m_fw != NULL) { - dev_info(dev, "firmware %s: loading from cache\n", - i2400m->fw_name); - ret = i2400m_fw_bootstrap(i2400m, i2400m_fw->fw, flags); - i2400m_fw_put(i2400m_fw); - goto out; - } - /* Load firmware files to memory. */ - for (itr = 0, bcf = NULL, ret = -ENOENT; ; itr++) { + itr = 0; + while(1) { fw_name = i2400m->bus_fw_names[itr]; if (fw_name == NULL) { dev_err(dev, "Could not find a usable firmware image\n"); - break; + ret = -ENOENT; + goto error_no_fw; } - d_printf(1, dev, "trying firmware %s (%d)\n", fw_name, itr); ret = request_firmware(&fw, fw_name, dev); - if (ret < 0) { + if (ret == 0) + break; /* got it */ + if (ret < 0) dev_err(dev, "fw %s: cannot load file: %d\n", fw_name, ret); - continue; - } - i2400m->fw_name = fw_name; - ret = i2400m_fw_bootstrap(i2400m, fw, flags); - release_firmware(fw); - if (ret >= 0) /* firmware loaded succesfully */ - break; - i2400m->fw_name = NULL; + itr++; } -out: + + bcf = (void *) fw->data; + i2400m->fw_name = fw_name; + ret = i2400m_fw_check(i2400m, bcf, fw->size); + if (ret < 0) + goto error_fw_bad; + ret = i2400m_fw_dnload(i2400m, bcf, fw->size, flags); +error_fw_bad: + release_firmware(fw); +error_no_fw: d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret); return ret; } EXPORT_SYMBOL_GPL(i2400m_dev_bootstrap); - - -void i2400m_fw_cache(struct i2400m *i2400m) -{ - int result; - struct i2400m_fw *i2400m_fw; - struct device *dev = i2400m_dev(i2400m); - - /* if there is anything there, free it -- now, this'd be weird */ - spin_lock(&i2400m->rx_lock); - i2400m_fw = i2400m->fw_cached; - spin_unlock(&i2400m->rx_lock); - if (i2400m_fw != NULL && i2400m_fw != (void *) ~0) { - i2400m_fw_put(i2400m_fw); - WARN(1, "%s:%u: still cached fw still present?\n", - __func__, __LINE__); - } - - if (i2400m->fw_name == NULL) { - dev_err(dev, "firmware n/a: can't cache\n"); - i2400m_fw = (void *) ~0; - goto out; - } - - i2400m_fw = kzalloc(sizeof(*i2400m_fw), GFP_ATOMIC); - if (i2400m_fw == NULL) - goto out; - kref_init(&i2400m_fw->kref); - result = request_firmware(&i2400m_fw->fw, i2400m->fw_name, dev); - if (result < 0) { - dev_err(dev, "firmware %s: failed to cache: %d\n", - i2400m->fw_name, result); - kfree(i2400m_fw); - i2400m_fw = (void *) ~0; - } else - dev_info(dev, "firmware %s: cached\n", i2400m->fw_name); -out: - spin_lock(&i2400m->rx_lock); - i2400m->fw_cached = i2400m_fw; - spin_unlock(&i2400m->rx_lock); -} - - -void i2400m_fw_uncache(struct i2400m *i2400m) -{ - struct i2400m_fw *i2400m_fw; - - spin_lock(&i2400m->rx_lock); - i2400m_fw = i2400m->fw_cached; - i2400m->fw_cached = NULL; - spin_unlock(&i2400m->rx_lock); - - if (i2400m_fw != NULL && i2400m_fw != (void *) ~0) - i2400m_fw_put(i2400m_fw); -} - diff --git a/trunk/drivers/net/wimax/i2400m/i2400m-sdio.h b/trunk/drivers/net/wimax/i2400m/i2400m-sdio.h index b9c4bed3b457..9c4e3189f7b5 100644 --- a/trunk/drivers/net/wimax/i2400m/i2400m-sdio.h +++ b/trunk/drivers/net/wimax/i2400m/i2400m-sdio.h @@ -67,7 +67,6 @@ /* Host-Device interface for SDIO */ enum { - I2400M_SDIO_BOOT_RETRIES = 3, I2400MS_BLK_SIZE = 256, I2400MS_PL_SIZE_MAX = 0x3E00, @@ -78,11 +77,9 @@ enum { I2400MS_INTR_GET_SIZE_ADDR = 0x2C, /* The number of ticks to wait for the device to signal that * it is ready */ - I2400MS_INIT_SLEEP_INTERVAL = 100, + I2400MS_INIT_SLEEP_INTERVAL = 10, /* How long to wait for the device to settle after reset */ I2400MS_SETTLE_TIME = 40, - /* The number of msec to wait for IOR after sending IOE */ - IWMC3200_IOR_TIMEOUT = 10, }; @@ -100,14 +97,6 @@ enum { * @tx_workqueue: workqeueue used for data TX; we don't use the * system's workqueue as that might cause deadlocks with code in * the bus-generic driver. - * - * @debugfs_dentry: dentry for the SDIO specific debugfs files - * - * Note this value is set to NULL upon destruction; this is - * because some routinges use it to determine if we are inside the - * probe() path or some other path. When debugfs is disabled, - * creation sets the dentry to '(void*) -ENODEV', which is valid - * for the test. */ struct i2400ms { struct i2400m i2400m; /* FIRST! See doc */ @@ -122,9 +111,6 @@ struct i2400ms { wait_queue_head_t bm_wfa_wq; int bm_wait_result; size_t bm_ack_size; - - /* Device is any of the iwmc3200 SKUs */ - unsigned iwmc3200:1; }; diff --git a/trunk/drivers/net/wimax/i2400m/i2400m-usb.h b/trunk/drivers/net/wimax/i2400m/i2400m-usb.h index 5cc0f279417e..6f76558b170f 100644 --- a/trunk/drivers/net/wimax/i2400m/i2400m-usb.h +++ b/trunk/drivers/net/wimax/i2400m/i2400m-usb.h @@ -88,13 +88,6 @@ struct edc { u16 errorcount; }; -struct i2400m_endpoint_cfg { - unsigned char bulk_out; - unsigned char notification; - unsigned char reset_cold; - unsigned char bulk_in; -}; - static inline void edc_init(struct edc *edc) { edc->timestart = jiffies; @@ -144,13 +137,15 @@ static inline int edc_inc(struct edc *edc, u16 max_err, u16 timeframe) /* Host-Device interface for USB */ enum { - I2400M_USB_BOOT_RETRIES = 3, I2400MU_MAX_NOTIFICATION_LEN = 256, I2400MU_BLK_SIZE = 16, I2400MU_PL_SIZE_MAX = 0x3EFF, - /* Device IDs */ - USB_DEVICE_ID_I6050 = 0x0186, + /* Endpoints */ + I2400MU_EP_BULK_OUT = 0, + I2400MU_EP_NOTIFICATION, + I2400MU_EP_RESET_COLD, + I2400MU_EP_BULK_IN, }; @@ -220,7 +215,6 @@ struct i2400mu { struct usb_device *usb_dev; struct usb_interface *usb_iface; struct edc urb_edc; /* Error density counter */ - struct i2400m_endpoint_cfg endpoint_cfg; struct urb *notif_urb; struct task_struct *tx_kthread; diff --git a/trunk/drivers/net/wimax/i2400m/i2400m.h b/trunk/drivers/net/wimax/i2400m/i2400m.h index 04df9bbe340f..60330f313f27 100644 --- a/trunk/drivers/net/wimax/i2400m/i2400m.h +++ b/trunk/drivers/net/wimax/i2400m/i2400m.h @@ -117,31 +117,17 @@ * well as i2400m->wimax_dev.net_dev and call i2400m_setup(). The * i2400m driver will only register with the WiMAX and network stacks; * the only access done to the device is to read the MAC address so we - * can register a network device. - * - * The high-level call flow is: - * - * bus_probe() - * i2400m_setup() - * i2400m->bus_setup() - * boot rom initialization / read mac addr - * network / WiMAX stacks registration - * i2400m_dev_start() - * i2400m->bus_dev_start() - * i2400m_dev_initialize() - * - * The reverse applies for a disconnect() call: - * - * bus_disconnect() - * i2400m_release() - * i2400m_dev_stop() - * i2400m_dev_shutdown() - * i2400m->bus_dev_stop() - * network / WiMAX stack unregistration - * i2400m->bus_release() + * can register a network device. This calls i2400m_dev_start() to + * load firmware, setup communication with the device and configure it + * for operation. * * At this point, control and data communications are possible. * + * On disconnect/driver unload, the bus-specific disconnect function + * calls i2400m_release() to undo i2400m_setup(). i2400m_dev_stop() + * shuts the firmware down and releases resources uses to communicate + * with the device. + * * While the device is up, it might reset. The bus-specific driver has * to catch that situation and call i2400m_dev_reset_handle() to deal * with it (reset the internal driver structures and go back to square @@ -162,6 +148,9 @@ /* Misc constants */ enum { + /* Firmware uploading */ + I2400M_BOOT_RETRIES = 3, + I3200_BOOT_RETRIES = 3, /* Size of the Boot Mode Command buffer */ I2400M_BM_CMD_BUF_SIZE = 16 * 1024, I2400M_BM_ACK_BUF_SIZE = 256, @@ -208,7 +197,6 @@ enum i2400m_reset_type { struct i2400m_reset_ctx; struct i2400m_roq; -struct i2400m_barker_db; /** * struct i2400m - descriptor for an Intel 2400m @@ -216,50 +204,27 @@ struct i2400m_barker_db; * Members marked with [fill] must be filled out/initialized before * calling i2400m_setup(). * - * Note the @bus_setup/@bus_release, @bus_dev_start/@bus_dev_release - * call pairs are very much doing almost the same, and depending on - * the underlying bus, some stuff has to be put in one or the - * other. The idea of setup/release is that they setup the minimal - * amount needed for loading firmware, where us dev_start/stop setup - * the rest needed to do full data/control traffic. - * * @bus_tx_block_size: [fill] SDIO imposes a 256 block size, USB 16, * so we have a tx_blk_size variable that the bus layer sets to * tell the engine how much of that we need. * * @bus_pl_size_max: [fill] Maximum payload size. * - * @bus_setup: [optional fill] Function called by the bus-generic code - * [i2400m_setup()] to setup the basic bus-specific communications - * to the the device needed to load firmware. See LIFE CYCLE above. + * @bus_dev_start: [fill] Function called by the bus-generic code + * [i2400m_dev_start()] to setup the bus-specific communications + * to the the device. See LIFE CYCLE above. * * NOTE: Doesn't need to upload the firmware, as that is taken * care of by the bus-generic code. * - * @bus_release: [optional fill] Function called by the bus-generic - * code [i2400m_release()] to shutdown the basic bus-specific - * communications to the the device needed to load firmware. See - * LIFE CYCLE above. + * @bus_dev_stop: [fill] Function called by the bus-generic code + * [i2400m_dev_stop()] to shutdown the bus-specific communications + * to the the device. See LIFE CYCLE above. * * This function does not need to reset the device, just tear down * all the host resources created to handle communication with * the device. * - * @bus_dev_start: [optional fill] Function called by the bus-generic - * code [i2400m_dev_start()] to do things needed to start the - * device. See LIFE CYCLE above. - * - * NOTE: Doesn't need to upload the firmware, as that is taken - * care of by the bus-generic code. - * - * @bus_dev_stop: [optional fill] Function called by the bus-generic - * code [i2400m_dev_stop()] to do things needed for stopping the - * device. See LIFE CYCLE above. - * - * This function does not need to reset the device, just tear down - * all the host resources created to handle communication with - * the device. - * * @bus_tx_kick: [fill] Function called by the bus-generic code to let * the bus-specific code know that there is data available in the * TX FIFO for transmission to the device. @@ -281,9 +246,6 @@ struct i2400m_barker_db; * process, so it cannot rely on common infrastructure being laid * out. * - * IMPORTANT: don't call reset on RT_BUS with i2400m->init_mutex - * held, as the .pre/.post reset handlers will deadlock. - * * @bus_bm_retries: [fill] How many times shall a firmware upload / * device initialization be retried? Different models of the same * device might need different values, hence it is set by the @@ -335,27 +297,6 @@ struct i2400m_barker_db; * force this to be the first field so that we can get from * netdev_priv() the right pointer. * - * @updown: the device is up and ready for transmitting control and - * data packets. This implies @ready (communication infrastructure - * with the device is ready) and the device's firmware has been - * loaded and the device initialized. - * - * Write to it only inside a i2400m->init_mutex protected area - * followed with a wmb(); rmb() before accesing (unless locked - * inside i2400m->init_mutex). Read access can be loose like that - * [just using rmb()] because the paths that use this also do - * other error checks later on. - * - * @ready: Communication infrastructure with the device is ready, data - * frames can start to be passed around (this is lighter than - * using the WiMAX state for certain hot paths). - * - * Write to it only inside a i2400m->init_mutex protected area - * followed with a wmb(); rmb() before accesing (unless locked - * inside i2400m->init_mutex). Read access can be loose like that - * [just using rmb()] because the paths that use this also do - * other error checks later on. - * * @rx_reorder: 1 if RX reordering is enabled; this can only be * set at probe time. * @@ -421,13 +362,6 @@ struct i2400m_barker_db; * delivered. Then the driver can release them to the host. See * drivers/net/i2400m/rx.c for details. * - * @rx_reports: reports received from the device that couldn't be - * processed because the driver wasn't still ready; when ready, - * they are pulled from here and chewed. - * - * @rx_reports_ws: Work struct used to kick a scan of the RX reports - * list and to process each. - * * @src_mac_addr: MAC address used to make ethernet packets be coming * from. This is generated at i2400m_setup() time and used during * the life cycle of the instance. See i2400m_fake_eth_header(). @@ -488,25 +422,6 @@ struct i2400m_barker_db; * * @fw_version: version of the firmware interface, Major.minor, * encoded in the high word and low word (major << 16 | minor). - * - * @fw_hdrs: NULL terminated array of pointers to the firmware - * headers. This is only available during firmware load time. - * - * @fw_cached: Used to cache firmware when the system goes to - * suspend/standby/hibernation (as on resume we can't read it). If - * NULL, no firmware was cached, read it. If ~0, you can't read - * any firmware files (the system still didn't come out of suspend - * and failed to cache one), so abort; otherwise, a valid cached - * firmware to be used. Access to this variable is protected by - * the spinlock i2400m->rx_lock. - * - * @barker: barker type that the device uses; this is initialized by - * i2400m_is_boot_barker() the first time it is called. Then it - * won't change during the life cycle of the device and everytime - * a boot barker is received, it is just verified for it being the - * same. - * - * @pm_notifier: used to register for PM events */ struct i2400m { struct wimax_dev wimax_dev; /* FIRST! See doc */ @@ -514,7 +429,7 @@ struct i2400m { unsigned updown:1; /* Network device is up or down */ unsigned boot_mode:1; /* is the device in boot mode? */ unsigned sboot:1; /* signed or unsigned fw boot */ - unsigned ready:1; /* Device comm infrastructure ready */ + unsigned ready:1; /* all probing steps done */ unsigned rx_reorder:1; /* RX reorder is enabled */ u8 trace_msg_from_user; /* echo rx msgs to 'trace' pipe */ /* typed u8 so /sys/kernel/debug/u8 can tweak */ @@ -525,10 +440,8 @@ struct i2400m { size_t bus_pl_size_max; unsigned bus_bm_retries; - int (*bus_setup)(struct i2400m *); int (*bus_dev_start)(struct i2400m *); void (*bus_dev_stop)(struct i2400m *); - void (*bus_release)(struct i2400m *); void (*bus_tx_kick)(struct i2400m *); int (*bus_reset)(struct i2400m *, enum i2400m_reset_type); ssize_t (*bus_bm_cmd_send)(struct i2400m *, @@ -555,8 +468,6 @@ struct i2400m { rx_num, rx_size_acc, rx_size_min, rx_size_max; struct i2400m_roq *rx_roq; /* not under rx_lock! */ u8 src_mac_addr[ETH_HLEN]; - struct list_head rx_reports; /* under rx_lock! */ - struct work_struct rx_report_ws; struct mutex msg_mutex; /* serialize command execution */ struct completion msg_completion; @@ -576,14 +487,39 @@ struct i2400m { struct dentry *debugfs_dentry; const char *fw_name; /* name of the current firmware image */ unsigned long fw_version; /* version of the firmware interface */ - const struct i2400m_bcf_hdr **fw_hdrs; - struct i2400m_fw *fw_cached; /* protected by rx_lock */ - struct i2400m_barker_db *barker; - - struct notifier_block pm_notifier; }; +/* + * Initialize a 'struct i2400m' from all zeroes + * + * This is a bus-generic API call. + */ +static inline +void i2400m_init(struct i2400m *i2400m) +{ + wimax_dev_init(&i2400m->wimax_dev); + + i2400m->boot_mode = 1; + i2400m->rx_reorder = 1; + init_waitqueue_head(&i2400m->state_wq); + + spin_lock_init(&i2400m->tx_lock); + i2400m->tx_pl_min = UINT_MAX; + i2400m->tx_size_min = UINT_MAX; + + spin_lock_init(&i2400m->rx_lock); + i2400m->rx_pl_min = UINT_MAX; + i2400m->rx_size_min = UINT_MAX; + + mutex_init(&i2400m->msg_mutex); + init_completion(&i2400m->msg_completion); + + mutex_init(&i2400m->init_mutex); + /* wake_tx_ws is initialized in i2400m_tx_setup() */ +} + + /* * Bus-generic internal APIs * ------------------------- @@ -641,14 +577,6 @@ extern void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *); extern int i2400m_dev_bootstrap(struct i2400m *, enum i2400m_bri); extern int i2400m_read_mac_addr(struct i2400m *); extern int i2400m_bootrom_init(struct i2400m *, enum i2400m_bri); -extern int i2400m_is_boot_barker(struct i2400m *, const void *, size_t); -static inline -int i2400m_is_d2h_barker(const void *buf) -{ - const __le32 *barker = buf; - return le32_to_cpu(*barker) == I2400M_D2H_MSG_BARKER; -} -extern void i2400m_unknown_barker(struct i2400m *, const void *, size_t); /* Make/grok boot-rom header commands */ @@ -716,8 +644,6 @@ unsigned i2400m_brh_get_signature(const struct i2400m_bootrom_header *hdr) /* * Driver / device setup and internal functions */ -extern void i2400m_init(struct i2400m *); -extern int i2400m_reset(struct i2400m *, enum i2400m_reset_type); extern void i2400m_netdev_setup(struct net_device *net_dev); extern int i2400m_sysfs_setup(struct device_driver *); extern void i2400m_sysfs_release(struct device_driver *); @@ -728,14 +654,10 @@ extern void i2400m_tx_release(struct i2400m *); extern int i2400m_rx_setup(struct i2400m *); extern void i2400m_rx_release(struct i2400m *); -extern void i2400m_fw_cache(struct i2400m *); -extern void i2400m_fw_uncache(struct i2400m *); - extern void i2400m_net_rx(struct i2400m *, struct sk_buff *, unsigned, const void *, int); extern void i2400m_net_erx(struct i2400m *, struct sk_buff *, enum i2400m_cs); -extern void i2400m_net_wake_stop(struct i2400m *); enum i2400m_pt; extern int i2400m_tx(struct i2400m *, const void *, size_t, enum i2400m_pt); @@ -750,12 +672,14 @@ static inline int i2400m_debugfs_add(struct i2400m *i2400m) static inline void i2400m_debugfs_rm(struct i2400m *i2400m) {} #endif -/* Initialize/shutdown the device */ +/* Called by _dev_start()/_dev_stop() to initialize the device itself */ extern int i2400m_dev_initialize(struct i2400m *); extern void i2400m_dev_shutdown(struct i2400m *); extern struct attribute_group i2400m_dev_attr_group; +extern int i2400m_schedule_work(struct i2400m *, + void (*)(struct work_struct *), gfp_t); /* HDI message's payload description handling */ @@ -800,9 +724,7 @@ void i2400m_put(struct i2400m *i2400m) dev_put(i2400m->wimax_dev.net_dev); } -extern int i2400m_dev_reset_handle(struct i2400m *, const char *); -extern int i2400m_pre_reset(struct i2400m *); -extern int i2400m_post_reset(struct i2400m *); +extern int i2400m_dev_reset_handle(struct i2400m *); /* * _setup()/_release() are called by the probe/disconnect functions of @@ -815,6 +737,20 @@ extern int i2400m_rx(struct i2400m *, struct sk_buff *); extern struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *, size_t *); extern void i2400m_tx_msg_sent(struct i2400m *); +static const __le32 i2400m_NBOOT_BARKER[4] = { + cpu_to_le32(I2400M_NBOOT_BARKER), + cpu_to_le32(I2400M_NBOOT_BARKER), + cpu_to_le32(I2400M_NBOOT_BARKER), + cpu_to_le32(I2400M_NBOOT_BARKER) +}; + +static const __le32 i2400m_SBOOT_BARKER[4] = { + cpu_to_le32(I2400M_SBOOT_BARKER), + cpu_to_le32(I2400M_SBOOT_BARKER), + cpu_to_le32(I2400M_SBOOT_BARKER), + cpu_to_le32(I2400M_SBOOT_BARKER) +}; + extern int i2400m_power_save_disabled; /* @@ -837,12 +773,10 @@ struct device *i2400m_dev(struct i2400m *i2400m) struct i2400m_work { struct work_struct ws; struct i2400m *i2400m; - size_t pl_size; u8 pl[0]; }; - -extern int i2400m_schedule_work(struct i2400m *, - void (*)(struct work_struct *), gfp_t, +extern int i2400m_queue_work(struct i2400m *, + void (*)(struct work_struct *), gfp_t, const void *, size_t); extern int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *, @@ -855,7 +789,6 @@ extern void i2400m_msg_ack_hook(struct i2400m *, const struct i2400m_l3l4_hdr *, size_t); extern void i2400m_report_hook(struct i2400m *, const struct i2400m_l3l4_hdr *, size_t); -extern void i2400m_report_hook_work(struct work_struct *); extern int i2400m_cmd_enter_powersave(struct i2400m *); extern int i2400m_cmd_get_state(struct i2400m *); extern int i2400m_cmd_exit_idle(struct i2400m *); @@ -916,12 +849,6 @@ void __i2400m_msleep(unsigned ms) #endif } - -/* module initialization helpers */ -extern int i2400m_barker_db_init(const char *); -extern void i2400m_barker_db_exit(void); - - /* Module parameters */ extern int i2400m_idle_mode_disabled; diff --git a/trunk/drivers/net/wimax/i2400m/netdev.c b/trunk/drivers/net/wimax/i2400m/netdev.c index 599aa4eb9baa..796396cb4c82 100644 --- a/trunk/drivers/net/wimax/i2400m/netdev.c +++ b/trunk/drivers/net/wimax/i2400m/netdev.c @@ -74,7 +74,6 @@ */ #include #include -#include #include "i2400m.h" @@ -89,10 +88,7 @@ enum { * The MTU is 1400 or less */ I2400M_MAX_MTU = 1400, - /* 20 secs? yep, this is the maximum timeout that the device - * might take to get out of IDLE / negotiate it with the base - * station. We add 1sec for good measure. */ - I2400M_TX_TIMEOUT = 21 * HZ, + I2400M_TX_TIMEOUT = HZ, I2400M_TX_QLEN = 5, }; @@ -105,19 +101,22 @@ int i2400m_open(struct net_device *net_dev) struct device *dev = i2400m_dev(i2400m); d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m); - /* Make sure we wait until init is complete... */ - mutex_lock(&i2400m->init_mutex); - if (i2400m->updown) - result = 0; - else + if (i2400m->ready == 0) { + dev_err(dev, "Device is still initializing\n"); result = -EBUSY; - mutex_unlock(&i2400m->init_mutex); + } else + result = 0; d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n", net_dev, i2400m, result); return result; } +/* + * + * On kernel versions where cancel_work_sync() didn't return anything, + * we rely on wake_tx_skb() being non-NULL. + */ static int i2400m_stop(struct net_device *net_dev) { @@ -125,7 +124,21 @@ int i2400m_stop(struct net_device *net_dev) struct device *dev = i2400m_dev(i2400m); d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m); - i2400m_net_wake_stop(i2400m); + /* See i2400m_hard_start_xmit(), references are taken there + * and here we release them if the work was still + * pending. Note we can't differentiate work not pending vs + * never scheduled, so the NULL check does that. */ + if (cancel_work_sync(&i2400m->wake_tx_ws) == 0 + && i2400m->wake_tx_skb != NULL) { + unsigned long flags; + struct sk_buff *wake_tx_skb; + spin_lock_irqsave(&i2400m->tx_lock, flags); + wake_tx_skb = i2400m->wake_tx_skb; /* compat help */ + i2400m->wake_tx_skb = NULL; /* compat help */ + spin_unlock_irqrestore(&i2400m->tx_lock, flags); + i2400m_put(i2400m); + kfree_skb(wake_tx_skb); + } d_fnend(3, dev, "(net_dev %p [i2400m %p]) = 0\n", net_dev, i2400m); return 0; } @@ -154,7 +167,6 @@ void i2400m_wake_tx_work(struct work_struct *ws) { int result; struct i2400m *i2400m = container_of(ws, struct i2400m, wake_tx_ws); - struct net_device *net_dev = i2400m->wimax_dev.net_dev; struct device *dev = i2400m_dev(i2400m); struct sk_buff *skb = i2400m->wake_tx_skb; unsigned long flags; @@ -170,36 +182,27 @@ void i2400m_wake_tx_work(struct work_struct *ws) dev_err(dev, "WAKE&TX: skb dissapeared!\n"); goto out_put; } - /* If we have, somehow, lost the connection after this was - * queued, don't do anything; this might be the device got - * reset or just disconnected. */ - if (unlikely(!netif_carrier_ok(net_dev))) - goto out_kfree; result = i2400m_cmd_exit_idle(i2400m); if (result == -EILSEQ) result = 0; if (result < 0) { dev_err(dev, "WAKE&TX: device didn't get out of idle: " - "%d - resetting\n", result); - i2400m_reset(i2400m, I2400M_RT_BUS); - goto error; + "%d\n", result); + goto error; } result = wait_event_timeout(i2400m->state_wq, - i2400m->state != I2400M_SS_IDLE, - net_dev->watchdog_timeo - HZ/2); + i2400m->state != I2400M_SS_IDLE, 5 * HZ); if (result == 0) result = -ETIMEDOUT; if (result < 0) { dev_err(dev, "WAKE&TX: error waiting for device to exit IDLE: " - "%d - resetting\n", result); - i2400m_reset(i2400m, I2400M_RT_BUS); + "%d\n", result); goto error; } msleep(20); /* device still needs some time or it drops it */ result = i2400m_tx(i2400m, skb->data, skb->len, I2400M_PT_DATA); + netif_wake_queue(i2400m->wimax_dev.net_dev); error: - netif_wake_queue(net_dev); -out_kfree: kfree_skb(skb); /* refcount transferred by _hard_start_xmit() */ out_put: i2400m_put(i2400m); @@ -226,38 +229,6 @@ void i2400m_tx_prep_header(struct sk_buff *skb) } - -/* - * Cleanup resources acquired during i2400m_net_wake_tx() - * - * This is called by __i2400m_dev_stop and means we have to make sure - * the workqueue is flushed from any pending work. - */ -void i2400m_net_wake_stop(struct i2400m *i2400m) -{ - struct device *dev = i2400m_dev(i2400m); - - d_fnstart(3, dev, "(i2400m %p)\n", i2400m); - /* See i2400m_hard_start_xmit(), references are taken there - * and here we release them if the work was still - * pending. Note we can't differentiate work not pending vs - * never scheduled, so the NULL check does that. */ - if (cancel_work_sync(&i2400m->wake_tx_ws) == 0 - && i2400m->wake_tx_skb != NULL) { - unsigned long flags; - struct sk_buff *wake_tx_skb; - spin_lock_irqsave(&i2400m->tx_lock, flags); - wake_tx_skb = i2400m->wake_tx_skb; /* compat help */ - i2400m->wake_tx_skb = NULL; /* compat help */ - spin_unlock_irqrestore(&i2400m->tx_lock, flags); - i2400m_put(i2400m); - kfree_skb(wake_tx_skb); - } - d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); - return; -} - - /* * TX an skb to an idle device * @@ -371,20 +342,6 @@ netdev_tx_t i2400m_hard_start_xmit(struct sk_buff *skb, int result; d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev); - if (skb_header_cloned(skb)) { - /* - * Make tcpdump/wireshark happy -- if they are - * running, the skb is cloned and we will overwrite - * the mac fields in i2400m_tx_prep_header. Expand - * seems to fix this... - */ - result = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); - if (result) { - result = NETDEV_TX_BUSY; - goto error_expand; - } - } - if (i2400m->state == I2400M_SS_IDLE) result = i2400m_net_wake_tx(i2400m, net_dev, skb); else @@ -395,11 +352,10 @@ netdev_tx_t i2400m_hard_start_xmit(struct sk_buff *skb, net_dev->stats.tx_packets++; net_dev->stats.tx_bytes += skb->len; } - result = NETDEV_TX_OK; -error_expand: kfree_skb(skb); - d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result); - return result; + + d_fnend(3, dev, "(skb %p net_dev %p)\n", skb, net_dev); + return NETDEV_TX_OK; } @@ -603,22 +559,6 @@ static const struct net_device_ops i2400m_netdev_ops = { .ndo_change_mtu = i2400m_change_mtu, }; -static void i2400m_get_drvinfo(struct net_device *net_dev, - struct ethtool_drvinfo *info) -{ - struct i2400m *i2400m = net_dev_to_i2400m(net_dev); - - strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1); - strncpy(info->fw_version, i2400m->fw_name, sizeof(info->fw_version) - 1); - if (net_dev->dev.parent) - strncpy(info->bus_info, dev_name(net_dev->dev.parent), - sizeof(info->bus_info) - 1); -} - -static const struct ethtool_ops i2400m_ethtool_ops = { - .get_drvinfo = i2400m_get_drvinfo, - .get_link = ethtool_op_get_link, -}; /** * i2400m_netdev_setup - Setup setup @net_dev's i2400m private data @@ -640,7 +580,6 @@ void i2400m_netdev_setup(struct net_device *net_dev) & ~IFF_MULTICAST); net_dev->watchdog_timeo = I2400M_TX_TIMEOUT; net_dev->netdev_ops = &i2400m_netdev_ops; - net_dev->ethtool_ops = &i2400m_ethtool_ops; d_fnend(3, NULL, "(net_dev %p) = void\n", net_dev); } EXPORT_SYMBOL_GPL(i2400m_netdev_setup); diff --git a/trunk/drivers/net/wimax/i2400m/rx.c b/trunk/drivers/net/wimax/i2400m/rx.c index e3d2a9de023c..07c32e68909f 100644 --- a/trunk/drivers/net/wimax/i2400m/rx.c +++ b/trunk/drivers/net/wimax/i2400m/rx.c @@ -158,104 +158,30 @@ struct i2400m_report_hook_args { struct sk_buff *skb_rx; const struct i2400m_l3l4_hdr *l3l4_hdr; size_t size; - struct list_head list_node; }; /* * Execute i2400m_report_hook in a workqueue * - * Goes over the list of queued reports in i2400m->rx_reports and - * processes them. + * Unpacks arguments from the deferred call, executes it and then + * drops the references. * - * NOTE: refcounts on i2400m are not needed because we flush the - * workqueue this runs on (i2400m->work_queue) before destroying - * i2400m. - */ -void i2400m_report_hook_work(struct work_struct *ws) -{ - struct i2400m *i2400m = container_of(ws, struct i2400m, rx_report_ws); - struct device *dev = i2400m_dev(i2400m); - struct i2400m_report_hook_args *args, *args_next; - LIST_HEAD(list); - unsigned long flags; - - while (1) { - spin_lock_irqsave(&i2400m->rx_lock, flags); - list_splice_init(&i2400m->rx_reports, &list); - spin_unlock_irqrestore(&i2400m->rx_lock, flags); - if (list_empty(&list)) - break; - else - d_printf(1, dev, "processing queued reports\n"); - list_for_each_entry_safe(args, args_next, &list, list_node) { - d_printf(2, dev, "processing queued report %p\n", args); - i2400m_report_hook(i2400m, args->l3l4_hdr, args->size); - kfree_skb(args->skb_rx); - list_del(&args->list_node); - kfree(args); - } - } -} - - -/* - * Flush the list of queued reports - */ -static -void i2400m_report_hook_flush(struct i2400m *i2400m) -{ - struct device *dev = i2400m_dev(i2400m); - struct i2400m_report_hook_args *args, *args_next; - LIST_HEAD(list); - unsigned long flags; - - d_printf(1, dev, "flushing queued reports\n"); - spin_lock_irqsave(&i2400m->rx_lock, flags); - list_splice_init(&i2400m->rx_reports, &list); - spin_unlock_irqrestore(&i2400m->rx_lock, flags); - list_for_each_entry_safe(args, args_next, &list, list_node) { - d_printf(2, dev, "flushing queued report %p\n", args); - kfree_skb(args->skb_rx); - list_del(&args->list_node); - kfree(args); - } -} - - -/* - * Queue a report for later processing - * - * @i2400m: device descriptor - * @skb_rx: skb that contains the payload (for reference counting) - * @l3l4_hdr: pointer to the control - * @size: size of the message + * Obvious NOTE: References are needed because we are a separate + * thread; otherwise the buffer changes under us because it is + * released by the original caller. */ static -void i2400m_report_hook_queue(struct i2400m *i2400m, struct sk_buff *skb_rx, - const void *l3l4_hdr, size_t size) +void i2400m_report_hook_work(struct work_struct *ws) { - struct device *dev = i2400m_dev(i2400m); - unsigned long flags; - struct i2400m_report_hook_args *args; - - args = kzalloc(sizeof(*args), GFP_NOIO); - if (args) { - args->skb_rx = skb_get(skb_rx); - args->l3l4_hdr = l3l4_hdr; - args->size = size; - spin_lock_irqsave(&i2400m->rx_lock, flags); - list_add_tail(&args->list_node, &i2400m->rx_reports); - spin_unlock_irqrestore(&i2400m->rx_lock, flags); - d_printf(2, dev, "queued report %p\n", args); - rmb(); /* see i2400m->ready's documentation */ - if (likely(i2400m->ready)) /* only send if up */ - queue_work(i2400m->work_queue, &i2400m->rx_report_ws); - } else { - if (printk_ratelimit()) - dev_err(dev, "%s:%u: Can't allocate %zu B\n", - __func__, __LINE__, sizeof(*args)); - } + struct i2400m_work *iw = + container_of(ws, struct i2400m_work, ws); + struct i2400m_report_hook_args *args = (void *) iw->pl; + if (iw->i2400m->ready) + i2400m_report_hook(iw->i2400m, args->l3l4_hdr, args->size); + kfree_skb(args->skb_rx); + i2400m_put(iw->i2400m); + kfree(iw); } @@ -369,29 +295,21 @@ void i2400m_rx_ctl(struct i2400m *i2400m, struct sk_buff *skb_rx, msg_type, size); d_dump(2, dev, l3l4_hdr, size); if (msg_type & I2400M_MT_REPORT_MASK) { - /* - * Process each report - * - * - has to be ran serialized as well - * - * - the handling might force the execution of - * commands. That might cause reentrancy issues with - * bus-specific subdrivers and workqueues, so the we - * run it in a separate workqueue. - * - * - when the driver is not yet ready to handle them, - * they are queued and at some point the queue is - * restarted [NOTE: we can't queue SKBs directly, as - * this might be a piece of a SKB, not the whole - * thing, and this is cheaper than cloning the - * SKB]. - * - * Note we don't do refcounting for the device - * structure; this is because before destroying - * 'i2400m', we make sure to flush the - * i2400m->work_queue, so there are no issues. - */ - i2400m_report_hook_queue(i2400m, skb_rx, l3l4_hdr, size); + /* These hooks have to be ran serialized; as well, the + * handling might force the execution of commands, and + * that might cause reentrancy issues with + * bus-specific subdrivers and workqueues. So we run + * it in a separate workqueue. */ + struct i2400m_report_hook_args args = { + .skb_rx = skb_rx, + .l3l4_hdr = l3l4_hdr, + .size = size + }; + if (unlikely(i2400m->ready == 0)) /* only send if up */ + return; + skb_get(skb_rx); + i2400m_queue_work(i2400m, i2400m_report_hook_work, + GFP_KERNEL, &args, sizeof(args)); if (unlikely(i2400m->trace_msg_from_user)) wimax_msg(&i2400m->wimax_dev, "echo", l3l4_hdr, size, GFP_KERNEL); @@ -445,6 +363,8 @@ void i2400m_rx_trace(struct i2400m *i2400m, msg_type & I2400M_MT_REPORT_MASK ? "REPORT" : "CMD/SET/GET", msg_type, size); d_dump(2, dev, l3l4_hdr, size); + if (unlikely(i2400m->ready == 0)) /* only send if up */ + return; result = wimax_msg(wimax_dev, "trace", l3l4_hdr, size, GFP_KERNEL); if (result < 0) dev_err(dev, "error sending trace to userspace: %d\n", @@ -828,7 +748,7 @@ void i2400m_roq_queue(struct i2400m *i2400m, struct i2400m_roq *roq, dev_err(dev, "SW BUG? queue nsn %d (lbn %u ws %u)\n", nsn, lbn, roq->ws); i2400m_roq_log_dump(i2400m, roq); - i2400m_reset(i2400m, I2400M_RT_WARM); + i2400m->bus_reset(i2400m, I2400M_RT_WARM); } else { __i2400m_roq_queue(i2400m, roq, skb, lbn, nsn); i2400m_roq_log_add(i2400m, roq, I2400M_RO_TYPE_PACKET, @@ -894,7 +814,7 @@ void i2400m_roq_queue_update_ws(struct i2400m *i2400m, struct i2400m_roq *roq, dev_err(dev, "SW BUG? queue_update_ws nsn %u (sn %u ws %u)\n", nsn, sn, roq->ws); i2400m_roq_log_dump(i2400m, roq); - i2400m_reset(i2400m, I2400M_RT_WARM); + i2400m->bus_reset(i2400m, I2400M_RT_WARM); } else { /* if the queue is empty, don't bother as we'd queue * it and inmediately unqueue it -- just deliver it */ @@ -1274,28 +1194,6 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) EXPORT_SYMBOL_GPL(i2400m_rx); -void i2400m_unknown_barker(struct i2400m *i2400m, - const void *buf, size_t size) -{ - struct device *dev = i2400m_dev(i2400m); - char prefix[64]; - const __le32 *barker = buf; - dev_err(dev, "RX: HW BUG? unknown barker %08x, " - "dropping %zu bytes\n", le32_to_cpu(*barker), size); - snprintf(prefix, sizeof(prefix), "%s %s: ", - dev_driver_string(dev), dev_name(dev)); - if (size > 64) { - print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, - 8, 4, buf, 64, 0); - printk(KERN_ERR "%s... (only first 64 bytes " - "dumped)\n", prefix); - } else - print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, - 8, 4, buf, size, 0); -} -EXPORT_SYMBOL(i2400m_unknown_barker); - - /* * Initialize the RX queue and infrastructure * @@ -1363,6 +1261,4 @@ void i2400m_rx_release(struct i2400m *i2400m) kfree(i2400m->rx_roq[0].log); kfree(i2400m->rx_roq); } - /* at this point, nothing can be received... */ - i2400m_report_hook_flush(i2400m); } diff --git a/trunk/drivers/net/wimax/i2400m/sdio-fw.c b/trunk/drivers/net/wimax/i2400m/sdio-fw.c index 8e025418f5be..7d6ec0f475f8 100644 --- a/trunk/drivers/net/wimax/i2400m/sdio-fw.c +++ b/trunk/drivers/net/wimax/i2400m/sdio-fw.c @@ -118,8 +118,7 @@ ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *i2400m, if (cmd_size > I2400M_BM_CMD_BUF_SIZE) goto error_too_big; - if (_cmd != i2400m->bm_cmd_buf) - memmove(i2400m->bm_cmd_buf, _cmd, cmd_size); + memcpy(i2400m->bm_cmd_buf, _cmd, cmd_size); /* Prep command */ cmd = i2400m->bm_cmd_buf; if (cmd_size_a > cmd_size) /* Zero pad space */ memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size); @@ -178,6 +177,10 @@ ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *i2400m, d_fnstart(5, dev, "(i2400m %p ack %p size %zu)\n", i2400m, ack, ack_size); + spin_lock(&i2400m->rx_lock); + i2400ms->bm_ack_size = -EINPROGRESS; + spin_unlock(&i2400m->rx_lock); + result = wait_event_timeout(i2400ms->bm_wfa_wq, i2400ms->bm_ack_size != -EINPROGRESS, 2 * HZ); @@ -196,10 +199,6 @@ ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *i2400m, size = min(ack_size, i2400ms->bm_ack_size); memcpy(ack, i2400m->bm_ack_buf, size); } - /* - * Remember always to clear the bm_ack_size to -EINPROGRESS - * after the RX data is processed - */ i2400ms->bm_ack_size = -EINPROGRESS; spin_unlock(&i2400m->rx_lock); diff --git a/trunk/drivers/net/wimax/i2400m/sdio-rx.c b/trunk/drivers/net/wimax/i2400m/sdio-rx.c index 8adf6c9b6f8f..321beadf6e47 100644 --- a/trunk/drivers/net/wimax/i2400m/sdio-rx.c +++ b/trunk/drivers/net/wimax/i2400m/sdio-rx.c @@ -53,7 +53,6 @@ * i2400ms_irq() * i2400ms_rx() * __i2400ms_rx_get_size() - * i2400m_is_boot_barker() * i2400m_rx() * * i2400ms_rx_setup() @@ -139,11 +138,6 @@ void i2400ms_rx(struct i2400ms *i2400ms) ret = rx_size; goto error_get_size; } - /* - * Hardware quirk: make sure to clear the INTR status register - * AFTER getting the data transfer size. - */ - sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret); ret = -ENOMEM; skb = alloc_skb(rx_size, GFP_ATOMIC); @@ -159,34 +153,25 @@ void i2400ms_rx(struct i2400ms *i2400ms) } rmb(); /* make sure we get boot_mode from dev_reset_handle */ - if (unlikely(i2400m->boot_mode == 1)) { + if (i2400m->boot_mode == 1) { spin_lock(&i2400m->rx_lock); i2400ms->bm_ack_size = rx_size; spin_unlock(&i2400m->rx_lock); memcpy(i2400m->bm_ack_buf, skb->data, rx_size); wake_up(&i2400ms->bm_wfa_wq); - d_printf(5, dev, "RX: SDIO boot mode message\n"); + dev_err(dev, "RX: SDIO boot mode message\n"); kfree_skb(skb); - goto out; - } - ret = -EIO; - if (unlikely(rx_size < sizeof(__le32))) { - dev_err(dev, "HW BUG? only %zu bytes received\n", rx_size); - goto error_bad_size; - } - if (likely(i2400m_is_d2h_barker(skb->data))) { - skb_put(skb, rx_size); - i2400m_rx(i2400m, skb); - } else if (unlikely(i2400m_is_boot_barker(i2400m, - skb->data, rx_size))) { - ret = i2400m_dev_reset_handle(i2400m, "device rebooted"); + } else if (unlikely(!memcmp(skb->data, i2400m_NBOOT_BARKER, + sizeof(i2400m_NBOOT_BARKER)) + || !memcmp(skb->data, i2400m_SBOOT_BARKER, + sizeof(i2400m_SBOOT_BARKER)))) { + ret = i2400m_dev_reset_handle(i2400m); dev_err(dev, "RX: SDIO reboot barker\n"); kfree_skb(skb); } else { - i2400m_unknown_barker(i2400m, skb->data, rx_size); - kfree_skb(skb); + skb_put(skb, rx_size); + i2400m_rx(i2400m, skb); } -out: d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms); return; @@ -194,7 +179,6 @@ void i2400ms_rx(struct i2400ms *i2400ms) kfree_skb(skb); error_alloc_skb: error_get_size: -error_bad_size: d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret); return; } @@ -225,6 +209,7 @@ void i2400ms_irq(struct sdio_func *func) dev_err(dev, "RX: BUG? got IRQ but no interrupt ready?\n"); goto error_no_irq; } + sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret); i2400ms_rx(i2400ms); error_no_irq: d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms); @@ -249,13 +234,6 @@ int i2400ms_rx_setup(struct i2400ms *i2400ms) init_waitqueue_head(&i2400ms->bm_wfa_wq); spin_lock(&i2400m->rx_lock); i2400ms->bm_wait_result = -EINPROGRESS; - /* - * Before we are about to enable the RX interrupt, make sure - * bm_ack_size is cleared to -EINPROGRESS which indicates - * no RX interrupt happened yet or the previous interrupt - * has been handled, we are ready to take the new interrupt - */ - i2400ms->bm_ack_size = -EINPROGRESS; spin_unlock(&i2400m->rx_lock); sdio_claim_host(func); diff --git a/trunk/drivers/net/wimax/i2400m/sdio-tx.c b/trunk/drivers/net/wimax/i2400m/sdio-tx.c index de66d068c9cb..5105a5ebc44f 100644 --- a/trunk/drivers/net/wimax/i2400m/sdio-tx.c +++ b/trunk/drivers/net/wimax/i2400m/sdio-tx.c @@ -149,8 +149,5 @@ int i2400ms_tx_setup(struct i2400ms *i2400ms) void i2400ms_tx_release(struct i2400ms *i2400ms) { - if (i2400ms->tx_workqueue) { - destroy_workqueue(i2400ms->tx_workqueue); - i2400ms->tx_workqueue = NULL; - } + destroy_workqueue(i2400ms->tx_workqueue); } diff --git a/trunk/drivers/net/wimax/i2400m/sdio.c b/trunk/drivers/net/wimax/i2400m/sdio.c index 76a50ac02ebb..2981e211e04f 100644 --- a/trunk/drivers/net/wimax/i2400m/sdio.c +++ b/trunk/drivers/net/wimax/i2400m/sdio.c @@ -43,9 +43,18 @@ * i2400m_release() * free_netdev(net_dev) * - * i2400ms_bus_reset() Called by i2400m_reset + * i2400ms_bus_reset() Called by i2400m->bus_reset * __i2400ms_reset() * __i2400ms_send_barker() + * + * i2400ms_bus_dev_start() Called by i2400m_dev_start() [who is + * i2400ms_tx_setup() called by i2400m_setup()] + * i2400ms_rx_setup() + * + * i2400ms_bus_dev_stop() Called by i2400m_dev_stop() [who is + * i2400ms_rx_release() is called by i2400m_release()] + * i2400ms_tx_release() + * */ #include @@ -62,14 +71,6 @@ static int ioe_timeout = 2; module_param(ioe_timeout, int, 0); -static char i2400ms_debug_params[128]; -module_param_string(debug, i2400ms_debug_params, sizeof(i2400ms_debug_params), - 0644); -MODULE_PARM_DESC(debug, - "String of space-separated NAME:VALUE pairs, where NAMEs " - "are the different debug submodules and VALUE are the " - "initial debug value to set."); - /* Our firmware file name list */ static const char *i2400ms_bus_fw_names[] = { #define I2400MS_FW_FILE_NAME "i2400m-fw-sdio-1.3.sbcf" @@ -94,24 +95,17 @@ static const struct i2400m_poke_table i2400ms_pokes[] = { * when we ask it to explicitly doing). Tries until a timeout is * reached. * - * The @maxtries argument indicates how many times (at most) it should - * be tried to enable the function. 0 means forever. This acts along - * with the timeout (ie: it'll stop trying as soon as the maximum - * number of tries is reached _or_ as soon as the timeout is reached). - * * The reverse of this is...sdio_disable_function() * * Returns: 0 if the SDIO function was enabled, < 0 errno code on * error (-ENODEV when it was unable to enable the function). */ static -int i2400ms_enable_function(struct i2400ms *i2400ms, unsigned maxtries) +int i2400ms_enable_function(struct sdio_func *func) { - struct sdio_func *func = i2400ms->func; u64 timeout; int err; struct device *dev = &func->dev; - unsigned tries = 0; d_fnstart(3, dev, "(func %p)\n", func); /* Setup timeout (FIXME: This needs to read the CIS table to @@ -121,14 +115,6 @@ int i2400ms_enable_function(struct i2400ms *i2400ms, unsigned maxtries) err = -ENODEV; while (err != 0 && time_before64(get_jiffies_64(), timeout)) { sdio_claim_host(func); - /* - * There is a sillicon bug on the IWMC3200, where the - * IOE timeout will cause problems on Moorestown - * platforms (system hang). We explicitly overwrite - * func->enable_timeout here to work around the issue. - */ - if (i2400ms->iwmc3200) - func->enable_timeout = IWMC3200_IOR_TIMEOUT; err = sdio_enable_func(func); if (0 == err) { sdio_release_host(func); @@ -136,11 +122,8 @@ int i2400ms_enable_function(struct i2400ms *i2400ms, unsigned maxtries) goto function_enabled; } d_printf(2, dev, "SDIO function failed to enable: %d\n", err); + sdio_disable_func(func); sdio_release_host(func); - if (maxtries > 0 && ++tries >= maxtries) { - err = -ETIME; - break; - } msleep(I2400MS_INIT_SLEEP_INTERVAL); } /* If timed out, device is not there yet -- get -ENODEV so @@ -157,99 +140,46 @@ int i2400ms_enable_function(struct i2400ms *i2400ms, unsigned maxtries) /* - * Setup minimal device communication infrastructure needed to at - * least be able to update the firmware. + * Setup driver resources needed to communicate with the device * - * Note the ugly trick: if we are in the probe path - * (i2400ms->debugfs_dentry == NULL), we only retry function - * enablement one, to avoid racing with the iwmc3200 top controller. + * The fw needs some time to settle, and it was just uploaded, + * so give it a break first. I'd prefer to just wait for the device to + * send something, but seems the poking we do to enable SDIO stuff + * interferes with it, so just give it a break before starting... */ static -int i2400ms_bus_setup(struct i2400m *i2400m) +int i2400ms_bus_dev_start(struct i2400m *i2400m) { int result; - struct i2400ms *i2400ms = - container_of(i2400m, struct i2400ms, i2400m); - struct device *dev = i2400m_dev(i2400m); + struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); struct sdio_func *func = i2400ms->func; - int retries; - - sdio_claim_host(func); - result = sdio_set_block_size(func, I2400MS_BLK_SIZE); - sdio_release_host(func); - if (result < 0) { - dev_err(dev, "Failed to set block size: %d\n", result); - goto error_set_blk_size; - } - - if (i2400ms->iwmc3200 && i2400ms->debugfs_dentry == NULL) - retries = 1; - else - retries = 0; - result = i2400ms_enable_function(i2400ms, retries); - if (result < 0) { - dev_err(dev, "Cannot enable SDIO function: %d\n", result); - goto error_func_enable; - } + struct device *dev = &func->dev; + d_fnstart(3, dev, "(i2400m %p)\n", i2400m); + msleep(200); result = i2400ms_tx_setup(i2400ms); if (result < 0) goto error_tx_setup; - result = i2400ms_rx_setup(i2400ms); - if (result < 0) - goto error_rx_setup; - return 0; - -error_rx_setup: - i2400ms_tx_release(i2400ms); -error_tx_setup: - sdio_claim_host(func); - sdio_disable_func(func); - sdio_release_host(func); -error_func_enable: -error_set_blk_size: + d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); return result; -} - - -/* - * Tear down minimal device communication infrastructure needed to at - * least be able to update the firmware. - */ -static -void i2400ms_bus_release(struct i2400m *i2400m) -{ - struct i2400ms *i2400ms = - container_of(i2400m, struct i2400ms, i2400m); - struct sdio_func *func = i2400ms->func; - i2400ms_rx_release(i2400ms); +error_tx_setup: i2400ms_tx_release(i2400ms); - sdio_claim_host(func); - sdio_disable_func(func); - sdio_release_host(func); + d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); + return result; } -/* - * Setup driver resources needed to communicate with the device - * - * The fw needs some time to settle, and it was just uploaded, - * so give it a break first. I'd prefer to just wait for the device to - * send something, but seems the poking we do to enable SDIO stuff - * interferes with it, so just give it a break before starting... - */ static -int i2400ms_bus_dev_start(struct i2400m *i2400m) +void i2400ms_bus_dev_stop(struct i2400m *i2400m) { struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); struct sdio_func *func = i2400ms->func; struct device *dev = &func->dev; d_fnstart(3, dev, "(i2400m %p)\n", i2400m); - msleep(200); - d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, 0); - return 0; + i2400ms_tx_release(i2400ms); + d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); } @@ -303,17 +233,18 @@ int __i2400ms_send_barker(struct i2400ms *i2400ms, * Warm reset: * * The device will be fully reset internally, but won't be - * disconnected from the bus (so no reenumeration will + * disconnected from the USB bus (so no reenumeration will * happen). Firmware upload will be neccessary. * - * The device will send a reboot barker that will trigger the driver - * to reinitialize the state via __i2400m_dev_reset_handle. + * The device will send a reboot barker in the notification endpoint + * that will trigger the driver to reinitialize the state + * automatically from notif.c:i2400m_notification_grok() into + * i2400m_dev_bootstrap_delayed(). * - * - * Cold and bus reset: + * Cold and bus (USB) reset: * * The device will be fully reset internally, disconnected from the - * bus an a reenumeration will happen. Firmware upload will be + * USB bus an a reenumeration will happen. Firmware upload will be * neccessary. Thus, we don't do any locking or struct * reinitialization, as we are going to be fully disconnected and * reenumerated. @@ -352,13 +283,25 @@ int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) sizeof(i2400m_COLD_BOOT_BARKER)); else if (rt == I2400M_RT_BUS) { do_bus_reset: + /* call netif_tx_disable() before sending IOE disable, + * so that all the tx from network layer are stopped + * while IOE is being reset. Make sure it is called + * only after register_netdev() was issued. + */ + if (i2400m->wimax_dev.net_dev->reg_state == NETREG_REGISTERED) + netif_tx_disable(i2400m->wimax_dev.net_dev); - i2400ms_bus_release(i2400m); + i2400ms_rx_release(i2400ms); + sdio_claim_host(i2400ms->func); + sdio_disable_func(i2400ms->func); + sdio_release_host(i2400ms->func); /* Wait for the device to settle */ msleep(40); - result = i2400ms_bus_setup(i2400m); + result = i2400ms_enable_function(i2400ms->func); + if (result >= 0) + i2400ms_rx_setup(i2400ms); } else BUG(); if (result < 0 && rt != I2400M_RT_BUS) { @@ -407,7 +350,7 @@ int i2400ms_debugfs_add(struct i2400ms *i2400ms) int result; struct dentry *dentry = i2400ms->i2400m.wimax_dev.debugfs_dentry; - dentry = debugfs_create_dir("i2400m-sdio", dentry); + dentry = debugfs_create_dir("i2400m-usb", dentry); result = PTR_ERR(dentry); if (IS_ERR(dentry)) { if (result == -ENODEV) @@ -424,7 +367,6 @@ int i2400ms_debugfs_add(struct i2400ms *i2400ms) error: debugfs_remove_recursive(i2400ms->debugfs_dentry); - i2400ms->debugfs_dentry = NULL; return result; } @@ -483,30 +425,37 @@ int i2400ms_probe(struct sdio_func *func, i2400m->bus_tx_block_size = I2400MS_BLK_SIZE; i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX; - i2400m->bus_setup = i2400ms_bus_setup; i2400m->bus_dev_start = i2400ms_bus_dev_start; - i2400m->bus_dev_stop = NULL; - i2400m->bus_release = i2400ms_bus_release; + i2400m->bus_dev_stop = i2400ms_bus_dev_stop; i2400m->bus_tx_kick = i2400ms_bus_tx_kick; i2400m->bus_reset = i2400ms_bus_reset; /* The iwmc3200-wimax sometimes requires the driver to try * hard when we paint it into a corner. */ - i2400m->bus_bm_retries = I2400M_SDIO_BOOT_RETRIES; + i2400m->bus_bm_retries = I3200_BOOT_RETRIES; i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send; i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack; i2400m->bus_fw_names = i2400ms_bus_fw_names; i2400m->bus_bm_mac_addr_impaired = 1; i2400m->bus_bm_pokes_table = &i2400ms_pokes[0]; - switch (func->device) { - case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX: - case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5: - i2400ms->iwmc3200 = 1; - break; - default: - i2400ms->iwmc3200 = 0; + sdio_claim_host(func); + result = sdio_set_block_size(func, I2400MS_BLK_SIZE); + sdio_release_host(func); + if (result < 0) { + dev_err(dev, "Failed to set block size: %d\n", result); + goto error_set_blk_size; + } + + result = i2400ms_enable_function(i2400ms->func); + if (result < 0) { + dev_err(dev, "Cannot enable SDIO function: %d\n", result); + goto error_func_enable; } + result = i2400ms_rx_setup(i2400ms); + if (result < 0) + goto error_rx_setup; + result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT); if (result < 0) { dev_err(dev, "cannot setup device: %d\n", result); @@ -524,6 +473,13 @@ int i2400ms_probe(struct sdio_func *func, error_debugfs_add: i2400m_release(i2400m); error_setup: + i2400ms_rx_release(i2400ms); +error_rx_setup: + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); +error_func_enable: +error_set_blk_size: sdio_set_drvdata(func, NULL); free_netdev(net_dev); error_alloc_netdev: @@ -541,9 +497,12 @@ void i2400ms_remove(struct sdio_func *func) d_fnstart(3, dev, "SDIO func %p\n", func); debugfs_remove_recursive(i2400ms->debugfs_dentry); - i2400ms->debugfs_dentry = NULL; + i2400ms_rx_release(i2400ms); i2400m_release(i2400m); sdio_set_drvdata(func, NULL); + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); free_netdev(net_dev); d_fnend(3, dev, "SDIO func %p\n", func); } @@ -553,8 +512,6 @@ const struct sdio_device_id i2400ms_sdio_ids[] = { /* Intel: i2400m WiMAX (iwmc3200) over SDIO */ { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX) }, - { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, - SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5) }, { /* end: all zeroes */ }, }; MODULE_DEVICE_TABLE(sdio, i2400ms_sdio_ids); @@ -572,8 +529,6 @@ struct sdio_driver i2400m_sdio_driver = { static int __init i2400ms_driver_init(void) { - d_parse_params(D_LEVEL, D_LEVEL_SIZE, i2400ms_debug_params, - "i2400m_sdio.debug"); return sdio_register_driver(&i2400m_sdio_driver); } module_init(i2400ms_driver_init); diff --git a/trunk/drivers/net/wimax/i2400m/tx.c b/trunk/drivers/net/wimax/i2400m/tx.c index 54480e8947f1..fa16ccf8e26a 100644 --- a/trunk/drivers/net/wimax/i2400m/tx.c +++ b/trunk/drivers/net/wimax/i2400m/tx.c @@ -310,7 +310,7 @@ size_t __i2400m_tx_tail_room(struct i2400m *i2400m) size_t tail_room; size_t tx_in; - if (unlikely(i2400m->tx_in == 0)) + if (unlikely(i2400m->tx_in) == 0) return I2400M_TX_BUF_SIZE; tx_in = i2400m->tx_in % I2400M_TX_BUF_SIZE; tail_room = I2400M_TX_BUF_SIZE - tx_in; @@ -642,9 +642,6 @@ int i2400m_tx(struct i2400m *i2400m, const void *buf, size_t buf_len, * current one is out of payload slots or we have a singleton, * close it and start a new one */ spin_lock_irqsave(&i2400m->tx_lock, flags); - result = -ESHUTDOWN; - if (i2400m->tx_buf == NULL) - goto error_tx_new; try_new: if (unlikely(i2400m->tx_msg == NULL)) i2400m_tx_new(i2400m); @@ -700,10 +697,7 @@ int i2400m_tx(struct i2400m *i2400m, const void *buf, size_t buf_len, } error_tx_new: spin_unlock_irqrestore(&i2400m->tx_lock, flags); - /* kick in most cases, except when the TX subsys is down, as - * it might free space */ - if (likely(result != -ESHUTDOWN)) - i2400m->bus_tx_kick(i2400m); + i2400m->bus_tx_kick(i2400m); /* always kick, might free up space */ d_fnend(3, dev, "(i2400m %p skb %p [%zu bytes] pt %u) = %d\n", i2400m, buf, buf_len, pl_type, result); return result; @@ -746,9 +740,6 @@ struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *i2400m, d_fnstart(3, dev, "(i2400m %p bus_size %p)\n", i2400m, bus_size); spin_lock_irqsave(&i2400m->tx_lock, flags); - tx_msg_moved = NULL; - if (i2400m->tx_buf == NULL) - goto out_unlock; skip: tx_msg_moved = NULL; if (i2400m->tx_in == i2400m->tx_out) { /* Empty FIFO? */ @@ -838,8 +829,6 @@ void i2400m_tx_msg_sent(struct i2400m *i2400m) d_fnstart(3, dev, "(i2400m %p)\n", i2400m); spin_lock_irqsave(&i2400m->tx_lock, flags); - if (i2400m->tx_buf == NULL) - goto out_unlock; i2400m->tx_out += i2400m->tx_msg_size; d_printf(2, dev, "TX: sent %zu b\n", (size_t) i2400m->tx_msg_size); i2400m->tx_msg_size = 0; @@ -848,7 +837,6 @@ void i2400m_tx_msg_sent(struct i2400m *i2400m) n = i2400m->tx_out / I2400M_TX_BUF_SIZE; i2400m->tx_out %= I2400M_TX_BUF_SIZE; i2400m->tx_in -= n * I2400M_TX_BUF_SIZE; -out_unlock: spin_unlock_irqrestore(&i2400m->tx_lock, flags); d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); } @@ -888,9 +876,5 @@ int i2400m_tx_setup(struct i2400m *i2400m) */ void i2400m_tx_release(struct i2400m *i2400m) { - unsigned long flags; - spin_lock_irqsave(&i2400m->tx_lock, flags); kfree(i2400m->tx_buf); - i2400m->tx_buf = NULL; - spin_unlock_irqrestore(&i2400m->tx_lock, flags); } diff --git a/trunk/drivers/net/wimax/i2400m/usb-fw.c b/trunk/drivers/net/wimax/i2400m/usb-fw.c index ce6b9938fde0..5ad287c228b8 100644 --- a/trunk/drivers/net/wimax/i2400m/usb-fw.c +++ b/trunk/drivers/net/wimax/i2400m/usb-fw.c @@ -99,10 +99,10 @@ ssize_t i2400mu_tx_bulk_out(struct i2400mu *i2400mu, void *buf, size_t buf_size) dev_err(dev, "BM-CMD: can't get autopm: %d\n", result); do_autopm = 0; } - epd = usb_get_epd(i2400mu->usb_iface, i2400mu->endpoint_cfg.bulk_out); + epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_BULK_OUT); pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress); retry: - result = usb_bulk_msg(i2400mu->usb_dev, pipe, buf, buf_size, &len, 200); + result = usb_bulk_msg(i2400mu->usb_dev, pipe, buf, buf_size, &len, HZ); switch (result) { case 0: if (len != buf_size) { @@ -113,28 +113,6 @@ ssize_t i2400mu_tx_bulk_out(struct i2400mu *i2400mu, void *buf, size_t buf_size) } result = len; break; - case -EPIPE: - /* - * Stall -- maybe the device is choking with our - * requests. Clear it and give it some time. If they - * happen to often, it might be another symptom, so we - * reset. - * - * No error handling for usb_clear_halt(0; if it - * works, the retry works; if it fails, this switch - * does the error handling for us. - */ - if (edc_inc(&i2400mu->urb_edc, - 10 * EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { - dev_err(dev, "BM-CMD: too many stalls in " - "URB; resetting device\n"); - usb_queue_reset_device(i2400mu->usb_iface); - /* fallthrough */ - } else { - usb_clear_halt(i2400mu->usb_dev, pipe); - msleep(10); /* give the device some time */ - goto retry; - } case -EINVAL: /* while removing driver */ case -ENODEV: /* dev disconnect ... */ case -ENOENT: /* just ignore it */ @@ -157,6 +135,7 @@ ssize_t i2400mu_tx_bulk_out(struct i2400mu *i2400mu, void *buf, size_t buf_size) result); goto retry; } + result = len; if (do_autopm) usb_autopm_put_interface(i2400mu->usb_iface); return result; @@ -193,8 +172,7 @@ ssize_t i2400mu_bus_bm_cmd_send(struct i2400m *i2400m, result = -E2BIG; if (cmd_size > I2400M_BM_CMD_BUF_SIZE) goto error_too_big; - if (_cmd != i2400m->bm_cmd_buf) - memmove(i2400m->bm_cmd_buf, _cmd, cmd_size); + memcpy(i2400m->bm_cmd_buf, _cmd, cmd_size); cmd = i2400m->bm_cmd_buf; if (cmd_size_a > cmd_size) /* Zero pad space */ memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size); @@ -248,8 +226,7 @@ int i2400mu_notif_submit(struct i2400mu *i2400mu, struct urb *urb, struct usb_endpoint_descriptor *epd; int pipe; - epd = usb_get_epd(i2400mu->usb_iface, - i2400mu->endpoint_cfg.notification); + epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_NOTIFICATION); pipe = usb_rcvintpipe(i2400mu->usb_dev, epd->bEndpointAddress); usb_fill_int_urb(urb, i2400mu->usb_dev, pipe, i2400m->bm_ack_buf, I2400M_BM_ACK_BUF_SIZE, @@ -351,8 +328,8 @@ ssize_t i2400mu_bus_bm_wait_for_ack(struct i2400m *i2400m, out: if (do_autopm) usb_autopm_put_interface(i2400mu->usb_iface); - d_fnend(8, dev, "(i2400m %p ack %p size %zu) = %ld\n", - i2400m, ack, ack_size, (long) result); + d_fnend(8, dev, "(i2400m %p ack %p size %zu) = %zd\n", + i2400m, ack, ack_size, result); return result; error_exceeded: diff --git a/trunk/drivers/net/wimax/i2400m/usb-notif.c b/trunk/drivers/net/wimax/i2400m/usb-notif.c index f88d1c6e35cb..6add27c3f35c 100644 --- a/trunk/drivers/net/wimax/i2400m/usb-notif.c +++ b/trunk/drivers/net/wimax/i2400m/usb-notif.c @@ -51,7 +51,6 @@ * * i2400mu_usb_notification_cb() Called when a URB is ready * i2400mu_notif_grok() - * i2400m_is_boot_barker() * i2400m_dev_reset_handle() * i2400mu_rx_kick() */ @@ -88,21 +87,32 @@ int i2400mu_notification_grok(struct i2400mu *i2400mu, const void *buf, d_fnstart(4, dev, "(i2400m %p buf %p buf_len %zu)\n", i2400mu, buf, buf_len); ret = -EIO; - if (buf_len < sizeof(i2400m_ZERO_BARKER)) + if (buf_len < sizeof(i2400m_NBOOT_BARKER)) /* Not a bug, just ignore */ goto error_bad_size; - ret = 0; - if (!memcmp(i2400m_ZERO_BARKER, buf, sizeof(i2400m_ZERO_BARKER))) { + if (!memcmp(i2400m_NBOOT_BARKER, buf, sizeof(i2400m_NBOOT_BARKER)) + || !memcmp(i2400m_SBOOT_BARKER, buf, sizeof(i2400m_SBOOT_BARKER))) + ret = i2400m_dev_reset_handle(i2400m); + else if (!memcmp(i2400m_ZERO_BARKER, buf, sizeof(i2400m_ZERO_BARKER))) { i2400mu_rx_kick(i2400mu); - goto out; + ret = 0; + } else { /* Unknown or unexpected data in the notif message */ + char prefix[64]; + ret = -EIO; + dev_err(dev, "HW BUG? Unknown/unexpected data in notification " + "message (%zu bytes)\n", buf_len); + snprintf(prefix, sizeof(prefix), "%s %s: ", + dev_driver_string(dev), dev_name(dev)); + if (buf_len > 64) { + print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, + 8, 4, buf, 64, 0); + printk(KERN_ERR "%s... (only first 64 bytes " + "dumped)\n", prefix); + } else + print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, + 8, 4, buf, buf_len, 0); } - ret = i2400m_is_boot_barker(i2400m, buf, buf_len); - if (unlikely(ret >= 0)) - ret = i2400m_dev_reset_handle(i2400m, "device rebooted"); - else /* Unknown or unexpected data in the notif message */ - i2400m_unknown_barker(i2400m, buf, buf_len); error_bad_size: -out: d_fnend(4, dev, "(i2400m %p buf %p buf_len %zu) = %d\n", i2400mu, buf, buf_len, ret); return ret; @@ -210,8 +220,7 @@ int i2400mu_notification_setup(struct i2400mu *i2400mu) dev_err(dev, "notification: cannot allocate URB\n"); goto error_alloc_urb; } - epd = usb_get_epd(i2400mu->usb_iface, - i2400mu->endpoint_cfg.notification); + epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_NOTIFICATION); usb_pipe = usb_rcvintpipe(i2400mu->usb_dev, epd->bEndpointAddress); usb_fill_int_urb(i2400mu->notif_urb, i2400mu->usb_dev, usb_pipe, buf, I2400MU_MAX_NOTIFICATION_LEN, diff --git a/trunk/drivers/net/wimax/i2400m/usb-rx.c b/trunk/drivers/net/wimax/i2400m/usb-rx.c index ba1b02362dfc..a314799967cf 100644 --- a/trunk/drivers/net/wimax/i2400m/usb-rx.c +++ b/trunk/drivers/net/wimax/i2400m/usb-rx.c @@ -204,7 +204,7 @@ struct sk_buff *i2400mu_rx(struct i2400mu *i2400mu, struct sk_buff *rx_skb) dev_err(dev, "RX: can't get autopm: %d\n", result); do_autopm = 0; } - epd = usb_get_epd(i2400mu->usb_iface, i2400mu->endpoint_cfg.bulk_in); + epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_BULK_IN); usb_pipe = usb_rcvbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress); retry: rx_size = skb_end_pointer(rx_skb) - rx_skb->data - rx_skb->len; @@ -214,7 +214,7 @@ struct sk_buff *i2400mu_rx(struct i2400mu *i2400mu, struct sk_buff *rx_skb) } result = usb_bulk_msg( i2400mu->usb_dev, usb_pipe, rx_skb->data + rx_skb->len, - rx_size, &read_size, 200); + rx_size, &read_size, HZ); usb_mark_last_busy(i2400mu->usb_dev); switch (result) { case 0: @@ -222,26 +222,6 @@ struct sk_buff *i2400mu_rx(struct i2400mu *i2400mu, struct sk_buff *rx_skb) goto retry; /* ZLP, just resubmit */ skb_put(rx_skb, read_size); break; - case -EPIPE: - /* - * Stall -- maybe the device is choking with our - * requests. Clear it and give it some time. If they - * happen to often, it might be another symptom, so we - * reset. - * - * No error handling for usb_clear_halt(0; if it - * works, the retry works; if it fails, this switch - * does the error handling for us. - */ - if (edc_inc(&i2400mu->urb_edc, - 10 * EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { - dev_err(dev, "BM-CMD: too many stalls in " - "URB; resetting device\n"); - goto do_reset; - } - usb_clear_halt(i2400mu->usb_dev, usb_pipe); - msleep(10); /* give the device some time */ - goto retry; case -EINVAL: /* while removing driver */ case -ENODEV: /* dev disconnect ... */ case -ENOENT: /* just ignore it */ @@ -303,7 +283,6 @@ struct sk_buff *i2400mu_rx(struct i2400mu *i2400mu, struct sk_buff *rx_skb) error_reset: dev_err(dev, "RX: maximum errors in URB exceeded; " "resetting device\n"); -do_reset: usb_queue_reset_device(i2400mu->usb_iface); rx_skb = ERR_PTR(result); goto out; @@ -337,15 +316,10 @@ int i2400mu_rxd(void *_i2400mu) size_t pending; int rx_size; struct sk_buff *rx_skb; - unsigned long flags; d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu); - spin_lock_irqsave(&i2400m->rx_lock, flags); - BUG_ON(i2400mu->rx_kthread != NULL); - i2400mu->rx_kthread = current; - spin_unlock_irqrestore(&i2400m->rx_lock, flags); while (1) { - d_printf(2, dev, "RX: waiting for messages\n"); + d_printf(2, dev, "TX: waiting for messages\n"); pending = 0; wait_event_interruptible( i2400mu->rx_wq, @@ -393,9 +367,6 @@ int i2400mu_rxd(void *_i2400mu) } result = 0; out: - spin_lock_irqsave(&i2400m->rx_lock, flags); - i2400mu->rx_kthread = NULL; - spin_unlock_irqrestore(&i2400m->rx_lock, flags); d_fnend(4, dev, "(i2400mu %p) = %d\n", i2400mu, result); return result; @@ -432,33 +403,18 @@ int i2400mu_rx_setup(struct i2400mu *i2400mu) struct i2400m *i2400m = &i2400mu->i2400m; struct device *dev = &i2400mu->usb_iface->dev; struct wimax_dev *wimax_dev = &i2400m->wimax_dev; - struct task_struct *kthread; - kthread = kthread_run(i2400mu_rxd, i2400mu, "%s-rx", - wimax_dev->name); - /* the kthread function sets i2400mu->rx_thread */ - if (IS_ERR(kthread)) { - result = PTR_ERR(kthread); + i2400mu->rx_kthread = kthread_run(i2400mu_rxd, i2400mu, "%s-rx", + wimax_dev->name); + if (IS_ERR(i2400mu->rx_kthread)) { + result = PTR_ERR(i2400mu->rx_kthread); dev_err(dev, "RX: cannot start thread: %d\n", result); } return result; } - void i2400mu_rx_release(struct i2400mu *i2400mu) { - unsigned long flags; - struct i2400m *i2400m = &i2400mu->i2400m; - struct device *dev = i2400m_dev(i2400m); - struct task_struct *kthread; - - spin_lock_irqsave(&i2400m->rx_lock, flags); - kthread = i2400mu->rx_kthread; - i2400mu->rx_kthread = NULL; - spin_unlock_irqrestore(&i2400m->rx_lock, flags); - if (kthread) - kthread_stop(kthread); - else - d_printf(1, dev, "RX: kthread had already exited\n"); + kthread_stop(i2400mu->rx_kthread); } diff --git a/trunk/drivers/net/wimax/i2400m/usb-tx.c b/trunk/drivers/net/wimax/i2400m/usb-tx.c index c65b9979f87e..dfd893356f49 100644 --- a/trunk/drivers/net/wimax/i2400m/usb-tx.c +++ b/trunk/drivers/net/wimax/i2400m/usb-tx.c @@ -101,11 +101,11 @@ int i2400mu_tx(struct i2400mu *i2400mu, struct i2400m_msg_hdr *tx_msg, dev_err(dev, "TX: can't get autopm: %d\n", result); do_autopm = 0; } - epd = usb_get_epd(i2400mu->usb_iface, i2400mu->endpoint_cfg.bulk_out); + epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_BULK_OUT); usb_pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress); retry: result = usb_bulk_msg(i2400mu->usb_dev, usb_pipe, - tx_msg, tx_msg_size, &sent_size, 200); + tx_msg, tx_msg_size, &sent_size, HZ); usb_mark_last_busy(i2400mu->usb_dev); switch (result) { case 0: @@ -115,28 +115,6 @@ int i2400mu_tx(struct i2400mu *i2400mu, struct i2400m_msg_hdr *tx_msg, result = -EIO; } break; - case -EPIPE: - /* - * Stall -- maybe the device is choking with our - * requests. Clear it and give it some time. If they - * happen to often, it might be another symptom, so we - * reset. - * - * No error handling for usb_clear_halt(0; if it - * works, the retry works; if it fails, this switch - * does the error handling for us. - */ - if (edc_inc(&i2400mu->urb_edc, - 10 * EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { - dev_err(dev, "BM-CMD: too many stalls in " - "URB; resetting device\n"); - usb_queue_reset_device(i2400mu->usb_iface); - /* fallthrough */ - } else { - usb_clear_halt(i2400mu->usb_dev, usb_pipe); - msleep(10); /* give the device some time */ - goto retry; - } case -EINVAL: /* while removing driver */ case -ENODEV: /* dev disconnect ... */ case -ENOENT: /* just ignore it */ @@ -183,15 +161,9 @@ int i2400mu_txd(void *_i2400mu) struct device *dev = &i2400mu->usb_iface->dev; struct i2400m_msg_hdr *tx_msg; size_t tx_msg_size; - unsigned long flags; d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu); - spin_lock_irqsave(&i2400m->tx_lock, flags); - BUG_ON(i2400mu->tx_kthread != NULL); - i2400mu->tx_kthread = current; - spin_unlock_irqrestore(&i2400m->tx_lock, flags); - while (1) { d_printf(2, dev, "TX: waiting for messages\n"); tx_msg = NULL; @@ -211,11 +183,6 @@ int i2400mu_txd(void *_i2400mu) if (result < 0) break; } - - spin_lock_irqsave(&i2400m->tx_lock, flags); - i2400mu->tx_kthread = NULL; - spin_unlock_irqrestore(&i2400m->tx_lock, flags); - d_fnend(4, dev, "(i2400mu %p) = %d\n", i2400mu, result); return result; } @@ -246,13 +213,11 @@ int i2400mu_tx_setup(struct i2400mu *i2400mu) struct i2400m *i2400m = &i2400mu->i2400m; struct device *dev = &i2400mu->usb_iface->dev; struct wimax_dev *wimax_dev = &i2400m->wimax_dev; - struct task_struct *kthread; - kthread = kthread_run(i2400mu_txd, i2400mu, "%s-tx", - wimax_dev->name); - /* the kthread function sets i2400mu->tx_thread */ - if (IS_ERR(kthread)) { - result = PTR_ERR(kthread); + i2400mu->tx_kthread = kthread_run(i2400mu_txd, i2400mu, "%s-tx", + wimax_dev->name); + if (IS_ERR(i2400mu->tx_kthread)) { + result = PTR_ERR(i2400mu->tx_kthread); dev_err(dev, "TX: cannot start thread: %d\n", result); } return result; @@ -260,17 +225,5 @@ int i2400mu_tx_setup(struct i2400mu *i2400mu) void i2400mu_tx_release(struct i2400mu *i2400mu) { - unsigned long flags; - struct i2400m *i2400m = &i2400mu->i2400m; - struct device *dev = i2400m_dev(i2400m); - struct task_struct *kthread; - - spin_lock_irqsave(&i2400m->tx_lock, flags); - kthread = i2400mu->tx_kthread; - i2400mu->tx_kthread = NULL; - spin_unlock_irqrestore(&i2400m->tx_lock, flags); - if (kthread) - kthread_stop(kthread); - else - d_printf(1, dev, "TX: kthread had already exited\n"); + kthread_stop(i2400mu->tx_kthread); } diff --git a/trunk/drivers/net/wimax/i2400m/usb.c b/trunk/drivers/net/wimax/i2400m/usb.c index 47e84ef355c5..7eadd11c815b 100644 --- a/trunk/drivers/net/wimax/i2400m/usb.c +++ b/trunk/drivers/net/wimax/i2400m/usb.c @@ -58,7 +58,7 @@ * i2400mu_rx_release() * i2400mu_tx_release() * - * i2400mu_bus_reset() Called by i2400m_reset + * i2400mu_bus_reset() Called by i2400m->bus_reset * __i2400mu_reset() * __i2400mu_send_barker() * usb_reset_device() @@ -71,25 +71,13 @@ #define D_SUBMODULE usb #include "usb-debug-levels.h" -static char i2400mu_debug_params[128]; -module_param_string(debug, i2400mu_debug_params, sizeof(i2400mu_debug_params), - 0644); -MODULE_PARM_DESC(debug, - "String of space-separated NAME:VALUE pairs, where NAMEs " - "are the different debug submodules and VALUE are the " - "initial debug value to set."); /* Our firmware file name */ -static const char *i2400mu_bus_fw_names_5x50[] = { +static const char *i2400mu_bus_fw_names[] = { #define I2400MU_FW_FILE_NAME_v1_4 "i2400m-fw-usb-1.4.sbcf" I2400MU_FW_FILE_NAME_v1_4, - NULL, -}; - - -static const char *i2400mu_bus_fw_names_6050[] = { -#define I6050U_FW_FILE_NAME_v1_5 "i6050-fw-usb-1.5.sbcf" - I6050U_FW_FILE_NAME_v1_5, +#define I2400MU_FW_FILE_NAME_v1_3 "i2400m-fw-usb-1.3.sbcf" + I2400MU_FW_FILE_NAME_v1_3, NULL, }; @@ -172,59 +160,14 @@ int __i2400mu_send_barker(struct i2400mu *i2400mu, epd = usb_get_epd(i2400mu->usb_iface, endpoint); pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress); memcpy(buffer, barker, barker_size); -retry: ret = usb_bulk_msg(i2400mu->usb_dev, pipe, buffer, barker_size, - &actual_len, 200); - switch (ret) { - case 0: - if (actual_len != barker_size) { /* Too short? drop it */ - dev_err(dev, "E: %s: short write (%d B vs %zu " - "expected)\n", - __func__, actual_len, barker_size); - ret = -EIO; - } - break; - case -EPIPE: - /* - * Stall -- maybe the device is choking with our - * requests. Clear it and give it some time. If they - * happen to often, it might be another symptom, so we - * reset. - * - * No error handling for usb_clear_halt(0; if it - * works, the retry works; if it fails, this switch - * does the error handling for us. - */ - if (edc_inc(&i2400mu->urb_edc, - 10 * EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { - dev_err(dev, "E: %s: too many stalls in " - "URB; resetting device\n", __func__); - usb_queue_reset_device(i2400mu->usb_iface); - /* fallthrough */ - } else { - usb_clear_halt(i2400mu->usb_dev, pipe); - msleep(10); /* give the device some time */ - goto retry; - } - case -EINVAL: /* while removing driver */ - case -ENODEV: /* dev disconnect ... */ - case -ENOENT: /* just ignore it */ - case -ESHUTDOWN: /* and exit */ - case -ECONNRESET: - ret = -ESHUTDOWN; - break; - default: /* Some error? */ - if (edc_inc(&i2400mu->urb_edc, - EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { - dev_err(dev, "E: %s: maximum errors in URB " - "exceeded; resetting device\n", - __func__); - usb_queue_reset_device(i2400mu->usb_iface); - } else { - dev_warn(dev, "W: %s: cannot send URB: %d\n", - __func__, ret); - goto retry; - } + &actual_len, HZ); + if (ret < 0) { + if (ret != -EINVAL) + dev_err(dev, "E: barker error: %d\n", ret); + } else if (actual_len != barker_size) { + dev_err(dev, "E: only %d bytes transmitted\n", actual_len); + ret = -EIO; } kfree(buffer); error_kzalloc: @@ -289,16 +232,15 @@ int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) d_fnstart(3, dev, "(i2400m %p rt %u)\n", i2400m, rt); if (rt == I2400M_RT_WARM) - result = __i2400mu_send_barker( - i2400mu, i2400m_WARM_BOOT_BARKER, - sizeof(i2400m_WARM_BOOT_BARKER), - i2400mu->endpoint_cfg.bulk_out); + result = __i2400mu_send_barker(i2400mu, i2400m_WARM_BOOT_BARKER, + sizeof(i2400m_WARM_BOOT_BARKER), + I2400MU_EP_BULK_OUT); else if (rt == I2400M_RT_COLD) - result = __i2400mu_send_barker( - i2400mu, i2400m_COLD_BOOT_BARKER, - sizeof(i2400m_COLD_BOOT_BARKER), - i2400mu->endpoint_cfg.reset_cold); + result = __i2400mu_send_barker(i2400mu, i2400m_COLD_BOOT_BARKER, + sizeof(i2400m_COLD_BOOT_BARKER), + I2400MU_EP_RESET_COLD); else if (rt == I2400M_RT_BUS) { +do_bus_reset: result = usb_reset_device(i2400mu->usb_dev); switch (result) { case 0: @@ -306,7 +248,7 @@ int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) case -ENODEV: case -ENOENT: case -ESHUTDOWN: - result = 0; + result = rt == I2400M_RT_WARM ? -ENODEV : 0; break; /* We assume the device is disconnected */ default: dev_err(dev, "USB reset failed (%d), giving up!\n", @@ -319,17 +261,10 @@ int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) if (result < 0 && result != -EINVAL /* device is gone */ && rt != I2400M_RT_BUS) { - /* - * Things failed -- resort to lower level reset, that - * we queue in another context; the reason for this is - * that the pre and post reset functionality requires - * the i2400m->init_mutex; RT_WARM and RT_COLD can - * come from areas where i2400m->init_mutex is taken. - */ dev_err(dev, "%s reset failed (%d); trying USB reset\n", rt == I2400M_RT_WARM ? "warm" : "cold", result); - usb_queue_reset_device(i2400mu->usb_iface); - result = -ENODEV; + rt = I2400M_RT_BUS; + goto do_bus_reset; } d_fnend(3, dev, "(i2400m %p rt %u) = %d\n", i2400m, rt, result); return result; @@ -467,33 +402,20 @@ int i2400mu_probe(struct usb_interface *iface, i2400m->bus_tx_block_size = I2400MU_BLK_SIZE; i2400m->bus_pl_size_max = I2400MU_PL_SIZE_MAX; - i2400m->bus_setup = NULL; i2400m->bus_dev_start = i2400mu_bus_dev_start; i2400m->bus_dev_stop = i2400mu_bus_dev_stop; - i2400m->bus_release = NULL; i2400m->bus_tx_kick = i2400mu_bus_tx_kick; i2400m->bus_reset = i2400mu_bus_reset; - i2400m->bus_bm_retries = I2400M_USB_BOOT_RETRIES; + i2400m->bus_bm_retries = I2400M_BOOT_RETRIES; i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send; i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack; + i2400m->bus_fw_names = i2400mu_bus_fw_names; i2400m->bus_bm_mac_addr_impaired = 0; - if (id->idProduct == USB_DEVICE_ID_I6050) { - i2400m->bus_fw_names = i2400mu_bus_fw_names_6050; - i2400mu->endpoint_cfg.bulk_out = 0; - i2400mu->endpoint_cfg.notification = 3; - i2400mu->endpoint_cfg.reset_cold = 2; - i2400mu->endpoint_cfg.bulk_in = 1; - } else { - i2400m->bus_fw_names = i2400mu_bus_fw_names_5x50; - i2400mu->endpoint_cfg.bulk_out = 0; - i2400mu->endpoint_cfg.notification = 1; - i2400mu->endpoint_cfg.reset_cold = 2; - i2400mu->endpoint_cfg.bulk_in = 3; - } #ifdef CONFIG_PM iface->needs_remote_wakeup = 1; /* autosuspend (15s delay) */ device_init_wakeup(dev, 1); + usb_autopm_enable(i2400mu->usb_iface); usb_dev->autosuspend_delay = 15 * HZ; usb_dev->autosuspend_disabled = 0; #endif @@ -561,10 +483,7 @@ void i2400mu_disconnect(struct usb_interface *iface) * So at the end, the three cases require common handling. * * If at the time of this call the device's firmware is not loaded, - * nothing has to be done. Note we can be "loose" about not reading - * i2400m->updown under i2400m->init_mutex. If it happens to change - * inmediately, other parts of the call flow will fail and effectively - * catch it. + * nothing has to be done. * * If the firmware is loaded, we need to: * @@ -603,7 +522,6 @@ int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg) #endif d_fnstart(3, dev, "(iface %p pm_msg %u)\n", iface, pm_msg.event); - rmb(); /* see i2400m->updown's documentation */ if (i2400m->updown == 0) goto no_firmware; if (i2400m->state == I2400M_SS_DATA_PATH_CONNECTED && is_autosuspend) { @@ -657,7 +575,6 @@ int i2400mu_resume(struct usb_interface *iface) struct i2400m *i2400m = &i2400mu->i2400m; d_fnstart(3, dev, "(iface %p)\n", iface); - rmb(); /* see i2400m->updown's documentation */ if (i2400m->updown == 0) { d_printf(1, dev, "fw was down, no resume neeed\n"); goto out; @@ -673,55 +590,8 @@ int i2400mu_resume(struct usb_interface *iface) } -static -int i2400mu_reset_resume(struct usb_interface *iface) -{ - int result; - struct device *dev = &iface->dev; - struct i2400mu *i2400mu = usb_get_intfdata(iface); - struct i2400m *i2400m = &i2400mu->i2400m; - - d_fnstart(3, dev, "(iface %p)\n", iface); - result = i2400m_dev_reset_handle(i2400m, "device reset on resume"); - d_fnend(3, dev, "(iface %p) = %d\n", iface, result); - return result < 0 ? result : 0; -} - - -/* - * Another driver or user space is triggering a reset on the device - * which contains the interface passed as an argument. Cease IO and - * save any device state you need to restore. - * - * If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if - * you are in atomic context. - */ -static -int i2400mu_pre_reset(struct usb_interface *iface) -{ - struct i2400mu *i2400mu = usb_get_intfdata(iface); - return i2400m_pre_reset(&i2400mu->i2400m); -} - - -/* - * The reset has completed. Restore any saved device state and begin - * using the device again. - * - * If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if - * you are in atomic context. - */ -static -int i2400mu_post_reset(struct usb_interface *iface) -{ - struct i2400mu *i2400mu = usb_get_intfdata(iface); - return i2400m_post_reset(&i2400mu->i2400m); -} - - static struct usb_device_id i2400mu_id_table[] = { - { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) }, { USB_DEVICE(0x8086, 0x0181) }, { USB_DEVICE(0x8086, 0x1403) }, { USB_DEVICE(0x8086, 0x1405) }, @@ -739,11 +609,8 @@ struct usb_driver i2400mu_driver = { .name = KBUILD_MODNAME, .suspend = i2400mu_suspend, .resume = i2400mu_resume, - .reset_resume = i2400mu_reset_resume, .probe = i2400mu_probe, .disconnect = i2400mu_disconnect, - .pre_reset = i2400mu_pre_reset, - .post_reset = i2400mu_post_reset, .id_table = i2400mu_id_table, .supports_autosuspend = 1, }; @@ -751,8 +618,6 @@ struct usb_driver i2400mu_driver = { static int __init i2400mu_driver_init(void) { - d_parse_params(D_LEVEL, D_LEVEL_SIZE, i2400mu_debug_params, - "i2400m_usb.debug"); return usb_register(&i2400mu_driver); } module_init(i2400mu_driver_init); @@ -767,7 +632,7 @@ void __exit i2400mu_driver_exit(void) module_exit(i2400mu_driver_exit); MODULE_AUTHOR("Intel Corporation "); -MODULE_DESCRIPTION("Driver for USB based Intel Wireless WiMAX Connection 2400M " - "(5x50 & 6050)"); +MODULE_DESCRIPTION("Intel 2400M WiMAX networking for USB"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(I2400MU_FW_FILE_NAME_v1_4); +MODULE_FIRMWARE(I2400MU_FW_FILE_NAME_v1_3); diff --git a/trunk/drivers/net/wireless/Kconfig b/trunk/drivers/net/wireless/Kconfig index 56dd6650c97a..85f8bf4112c1 100644 --- a/trunk/drivers/net/wireless/Kconfig +++ b/trunk/drivers/net/wireless/Kconfig @@ -16,9 +16,118 @@ menuconfig WLAN if WLAN +menuconfig WLAN_PRE80211 + bool "Wireless LAN (pre-802.11)" + depends on NETDEVICES + ---help--- + Say Y if you have any pre-802.11 wireless LAN hardware. + + This option does not affect the kernel build, it only + lets you choose drivers. + +config STRIP + tristate "STRIP (Metricom starmode radio IP)" + depends on INET && WLAN_PRE80211 + select WIRELESS_EXT + ---help--- + Say Y if you have a Metricom radio and intend to use Starmode Radio + IP. STRIP is a radio protocol developed for the MosquitoNet project + to send Internet traffic using Metricom radios. Metricom radios are + small, battery powered, 100kbit/sec packet radio transceivers, about + the size and weight of a cellular telephone. (You may also have heard + them called "Metricom modems" but we avoid the term "modem" because + it misleads many people into thinking that you can plug a Metricom + modem into a phone line and use it as a modem.) + + You can use STRIP on any Linux machine with a serial port, although + it is obviously most useful for people with laptop computers. If you + think you might get a Metricom radio in the future, there is no harm + in saying Y to STRIP now, except that it makes the kernel a bit + bigger. + + To compile this as a module, choose M here: the module will be + called strip. + +config ARLAN + tristate "Aironet Arlan 655 & IC2200 DS support" + depends on ISA && !64BIT && WLAN_PRE80211 + select WIRELESS_EXT + ---help--- + Aironet makes Arlan, a class of wireless LAN adapters. These use the + www.Telxon.com chip, which is also used on several similar cards. + This driver is tested on the 655 and IC2200 series cards. Look at + for the latest information. + + The driver is built as two modules, arlan and arlan-proc. The latter + is the /proc interface and is not needed most of time. + + On some computers the card ends up in non-valid state after some + time. Use a ping-reset script to clear it. + +config WAVELAN + tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support" + depends on ISA && WLAN_PRE80211 + select WIRELESS_EXT + select WEXT_SPY + select WEXT_PRIV + ---help--- + The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is + a Radio LAN (wireless Ethernet-like Local Area Network) using the + radio frequencies 900 MHz and 2.4 GHz. + + If you want to use an ISA WaveLAN card under Linux, say Y and read + the Ethernet-HOWTO, available from + . Some more specific + information is contained in + and in the source code + . + + You will also need the wireless tools package available from + . + Please read the man pages contained therein. + + To compile this driver as a module, choose M here: the module will be + called wavelan. + +config PCMCIA_WAVELAN + tristate "AT&T/Lucent old WaveLAN Pcmcia wireless support" + depends on PCMCIA && WLAN_PRE80211 + select WIRELESS_EXT + select WEXT_SPY + select WEXT_PRIV + help + Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA + (PC-card) wireless Ethernet networking card to your computer. This + driver is for the non-IEEE-802.11 Wavelan cards. + + To compile this driver as a module, choose M here: the module will be + called wavelan_cs. If unsure, say N. + +config PCMCIA_NETWAVE + tristate "Xircom Netwave AirSurfer Pcmcia wireless support" + depends on PCMCIA && WLAN_PRE80211 + select WIRELESS_EXT + select WEXT_PRIV + help + Say Y here if you intend to attach this type of PCMCIA (PC-card) + wireless Ethernet networking card to your computer. + + To compile this driver as a module, choose M here: the module will be + called netwave_cs. If unsure, say N. + + +menuconfig WLAN_80211 + bool "Wireless LAN (IEEE 802.11)" + depends on NETDEVICES + ---help--- + Say Y if you have any 802.11 wireless LAN hardware. + + This option does not affect the kernel build, it only + lets you choose drivers. + config PCMCIA_RAYCS tristate "Aviator/Raytheon 2.4GHz wireless support" - depends on PCMCIA + depends on PCMCIA && WLAN_80211 select WIRELESS_EXT select WEXT_SPY select WEXT_PRIV @@ -33,7 +142,7 @@ config PCMCIA_RAYCS config LIBERTAS_THINFIRM tristate "Marvell 8xxx Libertas WLAN driver support with thin firmware" - depends on MAC80211 + depends on WLAN_80211 && MAC80211 select FW_LOADER ---help--- A library for Marvell Libertas 8xxx devices using thinfirm. @@ -46,7 +155,7 @@ config LIBERTAS_THINFIRM_USB config AIRO tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards" - depends on ISA_DMA_API && (PCI || BROKEN) + depends on ISA_DMA_API && WLAN_80211 && (PCI || BROKEN) select WIRELESS_EXT select CRYPTO select WEXT_SPY @@ -66,7 +175,7 @@ config AIRO config ATMEL tristate "Atmel at76c50x chipset 802.11b support" - depends on (PCI || PCMCIA) + depends on (PCI || PCMCIA) && WLAN_80211 select WIRELESS_EXT select WEXT_PRIV select FW_LOADER @@ -101,7 +210,7 @@ config PCMCIA_ATMEL config AT76C50X_USB tristate "Atmel at76c503/at76c505/at76c505a USB cards" - depends on MAC80211 && USB + depends on MAC80211 && WLAN_80211 && USB select FW_LOADER ---help--- Enable support for USB Wireless devices using Atmel at76c503, @@ -109,9 +218,8 @@ config AT76C50X_USB config AIRO_CS tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards" - depends on PCMCIA && (BROKEN || !M32R) + depends on PCMCIA && (BROKEN || !M32R) && WLAN_80211 select WIRELESS_EXT - select WEXT_SPY select CRYPTO select CRYPTO_AES ---help--- @@ -130,7 +238,7 @@ config AIRO_CS config PCMCIA_WL3501 tristate "Planet WL3501 PCMCIA cards" - depends on EXPERIMENTAL && PCMCIA + depends on EXPERIMENTAL && PCMCIA && WLAN_80211 select WIRELESS_EXT select WEXT_SPY help @@ -140,7 +248,7 @@ config PCMCIA_WL3501 config PRISM54 tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus (DEPRECATED)' - depends on PCI && EXPERIMENTAL + depends on PCI && EXPERIMENTAL && WLAN_80211 select WIRELESS_EXT select WEXT_SPY select WEXT_PRIV @@ -164,7 +272,7 @@ config PRISM54 config USB_ZD1201 tristate "USB ZD1201 based Wireless device support" - depends on USB + depends on USB && WLAN_80211 select WIRELESS_EXT select WEXT_PRIV select FW_LOADER @@ -183,7 +291,7 @@ config USB_ZD1201 config USB_NET_RNDIS_WLAN tristate "Wireless RNDIS USB support" - depends on USB && EXPERIMENTAL + depends on USB && WLAN_80211 && EXPERIMENTAL depends on CFG80211 select USB_USBNET select USB_NET_CDCETHER @@ -211,7 +319,7 @@ config USB_NET_RNDIS_WLAN config RTL8180 tristate "Realtek 8180/8185 PCI support" - depends on MAC80211 && PCI && EXPERIMENTAL + depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL select EEPROM_93CX6 ---help--- This is a driver for RTL8180 and RTL8185 based cards. @@ -267,7 +375,7 @@ config RTL8180 config RTL8187 tristate "Realtek 8187 and 8187B USB support" - depends on MAC80211 && USB + depends on MAC80211 && USB && WLAN_80211 select EEPROM_93CX6 ---help--- This is a driver for RTL8187 and RTL8187B based cards. @@ -296,7 +404,7 @@ config RTL8187_LEDS config ADM8211 tristate "ADMtek ADM8211 support" - depends on MAC80211 && PCI && EXPERIMENTAL + depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL select CRC32 select EEPROM_93CX6 ---help--- @@ -323,7 +431,7 @@ config ADM8211 config MAC80211_HWSIM tristate "Simulated radio testing tool for mac80211" - depends on MAC80211 + depends on MAC80211 && WLAN_80211 ---help--- This driver is a developer testing tool that can be used to test IEEE 802.11 networking stack (mac80211) functionality. This is not @@ -336,7 +444,7 @@ config MAC80211_HWSIM config MWL8K tristate "Marvell 88W8xxx PCI/PCIe Wireless support" - depends on MAC80211 && PCI && EXPERIMENTAL + depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL ---help--- This driver supports Marvell TOPDOG 802.11 wireless cards. diff --git a/trunk/drivers/net/wireless/Makefile b/trunk/drivers/net/wireless/Makefile index 5d4ce4d2b32b..7a4647e78fd3 100644 --- a/trunk/drivers/net/wireless/Makefile +++ b/trunk/drivers/net/wireless/Makefile @@ -5,6 +5,16 @@ obj-$(CONFIG_IPW2100) += ipw2x00/ obj-$(CONFIG_IPW2200) += ipw2x00/ +obj-$(CONFIG_STRIP) += strip.o +obj-$(CONFIG_ARLAN) += arlan.o + +arlan-objs := arlan-main.o arlan-proc.o + +# Obsolete cards +obj-$(CONFIG_WAVELAN) += wavelan.o +obj-$(CONFIG_PCMCIA_NETWAVE) += netwave_cs.o +obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan_cs.o + obj-$(CONFIG_HERMES) += orinoco/ obj-$(CONFIG_AIRO) += airo.o diff --git a/trunk/drivers/staging/arlan/arlan-main.c b/trunk/drivers/net/wireless/arlan-main.c similarity index 100% rename from trunk/drivers/staging/arlan/arlan-main.c rename to trunk/drivers/net/wireless/arlan-main.c diff --git a/trunk/drivers/staging/arlan/arlan-proc.c b/trunk/drivers/net/wireless/arlan-proc.c similarity index 100% rename from trunk/drivers/staging/arlan/arlan-proc.c rename to trunk/drivers/net/wireless/arlan-proc.c diff --git a/trunk/drivers/staging/arlan/arlan.h b/trunk/drivers/net/wireless/arlan.h similarity index 100% rename from trunk/drivers/staging/arlan/arlan.h rename to trunk/drivers/net/wireless/arlan.h diff --git a/trunk/drivers/net/wireless/ath/Kconfig b/trunk/drivers/net/wireless/ath/Kconfig index 4e7a7fd695c8..6ce86cb37654 100644 --- a/trunk/drivers/net/wireless/ath/Kconfig +++ b/trunk/drivers/net/wireless/ath/Kconfig @@ -1,5 +1,6 @@ menuconfig ATH_COMMON tristate "Atheros Wireless Cards" + depends on WLAN_80211 depends on CFG80211 ---help--- This will enable the support for the Atheros wireless drivers. diff --git a/trunk/drivers/net/wireless/ath/ar9170/Kconfig b/trunk/drivers/net/wireless/ath/ar9170/Kconfig index d7a4799d20fb..05918f1e685a 100644 --- a/trunk/drivers/net/wireless/ath/ar9170/Kconfig +++ b/trunk/drivers/net/wireless/ath/ar9170/Kconfig @@ -1,6 +1,6 @@ config AR9170_USB tristate "Atheros AR9170 802.11n USB support" - depends on USB && MAC80211 + depends on USB && MAC80211 && WLAN_80211 select FW_LOADER help This is a driver for the Atheros "otus" 802.11n USB devices. diff --git a/trunk/drivers/net/wireless/ath/ath5k/Kconfig b/trunk/drivers/net/wireless/ath/ath5k/Kconfig index eb83b7b4d0e3..06d006675d7d 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/Kconfig +++ b/trunk/drivers/net/wireless/ath/ath5k/Kconfig @@ -1,6 +1,6 @@ config ATH5K tristate "Atheros 5xxx wireless cards support" - depends on PCI && MAC80211 + depends on PCI && MAC80211 && WLAN_80211 select MAC80211_LEDS select LEDS_CLASS select NEW_LEDS diff --git a/trunk/drivers/net/wireless/ath/ath5k/base.c b/trunk/drivers/net/wireless/ath/ath5k/base.c index cb3dc892d697..07c1e52b5a0c 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/base.c +++ b/trunk/drivers/net/wireless/ath/ath5k/base.c @@ -1146,6 +1146,7 @@ ath5k_mode_setup(struct ath5k_softc *sc) /* configure operational mode */ ath5k_hw_set_opmode(ah); + ath5k_hw_set_mcast_filter(ah, 0, 0); ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); } diff --git a/trunk/drivers/net/wireless/ath/ath5k/led.c b/trunk/drivers/net/wireless/ath/ath5k/led.c index d495890355d9..b767c3b67b24 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/led.c +++ b/trunk/drivers/net/wireless/ath/ath5k/led.c @@ -59,22 +59,16 @@ static const struct pci_device_id ath5k_led_devices[] = { { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) }, /* Acer Aspire One A150 (maximlevitsky@gmail.com) */ { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) }, - /* Acer Aspire One AO531h AO751h (keng-yu.lin@canonical.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe00d), ATH_LED(3, 0) }, /* Acer Ferrari 5000 (russ.dill@gmail.com) */ { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) }, /* E-machines E510 (tuliom@gmail.com) */ { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) }, - /* BenQ Joybook R55v (nowymarluk@wp.pl) */ - { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0100), ATH_LED(1, 0) }, /* Acer Extensa 5620z (nekoreeve@gmail.com) */ { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) }, /* Fukato Datacask Jupiter 1014a (mrb74@gmx.at) */ { ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) }, /* IBM ThinkPad AR5BXB6 (legovini@spiro.fisica.unipd.it) */ { ATH_SDEVICE(PCI_VENDOR_ID_IBM, 0x058a), ATH_LED(1, 0) }, - /* HP Compaq CQ60-206US (ddreggors@jumptv.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) }, /* HP Compaq C700 (nitrousnrg@gmail.com) */ { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) }, /* IBM-specific AR5212 (all others) */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/Kconfig b/trunk/drivers/net/wireless/ath/ath9k/Kconfig index b735fb399fb1..99ce066392a7 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/Kconfig +++ b/trunk/drivers/net/wireless/ath/ath9k/Kconfig @@ -3,7 +3,7 @@ config ATH9K_HW config ATH9K tristate "Atheros 802.11n wireless cards support" - depends on PCI && MAC80211 + depends on PCI && MAC80211 && WLAN_80211 select ATH9K_HW select MAC80211_LEDS select LEDS_CLASS diff --git a/trunk/drivers/net/wireless/ath/ath9k/ahb.c b/trunk/drivers/net/wireless/ath/ath9k/ahb.c index 329e6bc137ab..25531f231b67 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ahb.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ahb.c @@ -69,7 +69,6 @@ static int ath_ahb_probe(struct platform_device *pdev) int irq; int ret = 0; struct ath_hw *ah; - char hw_name[64]; if (!pdev->dev.platform_data) { dev_err(&pdev->dev, "no platform data specified\n"); @@ -134,11 +133,14 @@ 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", + "%s: Atheros AR%s MAC/BB Rev:%x, " + "AR%s RF Rev:%x, mem=0x%lx, irq=%d\n", wiphy_name(hw->wiphy), - hw_name, + ath_mac_bb_name(ah->hw_version.macVersion), + ah->hw_version.macRev, + ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)), + ah->hw_version.phyRev, (unsigned long)mem, irq); return 0; diff --git a/trunk/drivers/net/wireless/ath/ath9k/calib.c b/trunk/drivers/net/wireless/ath/ath9k/calib.c index 238a5744d8e9..551f8801459f 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/calib.c +++ b/trunk/drivers/net/wireless/ath/ath9k/calib.c @@ -877,7 +877,7 @@ static void ath9k_hw_9271_pa_cal(struct ath_hw *ah, bool is_reset) REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0); /* find off_6_1; */ - for (i = 6; i > 0; i--) { + for (i = 6; i >= 0; i--) { regVal = REG_READ(ah, 0x7834); regVal |= (1 << (20 + i)); REG_WRITE(ah, 0x7834, regVal); diff --git a/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 68db16690abf..58167d861dc6 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -1112,10 +1112,6 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); - - if (AR_SREV_9271_10(ah)) - REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, - pModal->txEndToRxOn); REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, pModal->thresh62); REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index 111ff049f75d..cab17c6c8a37 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -30,6 +30,8 @@ static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan); static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, struct ar5416_eeprom_def *pEepData, u32 reg, u32 value); +static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); +static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); MODULE_AUTHOR("Atheros Communications"); MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); @@ -452,6 +454,21 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) ah->power_mode = ATH9K_PM_UNDEFINED; } +static int ath9k_hw_rfattach(struct ath_hw *ah) +{ + bool rfStatus = false; + int ecode = 0; + + rfStatus = ath9k_hw_init_rf(ah, &ecode); + if (!rfStatus) { + ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, + "RF setup failed, status: %u\n", ecode); + return ecode; + } + + return 0; +} + static int ath9k_hw_rf_claim(struct ath_hw *ah) { u32 val; @@ -568,15 +585,9 @@ static int ath9k_hw_post_init(struct ath_hw *ah) ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah)); - if (!AR_SREV_9280_10_OR_LATER(ah)) { - ecode = ath9k_hw_rf_alloc_ext_banks(ah); - if (ecode) { - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "Failed allocating banks for " - "external radio\n"); - return ecode; - } - } + ecode = ath9k_hw_rfattach(ah); + if (ecode != 0) + return ecode; if (!AR_SREV_9100(ah)) { ath9k_hw_ani_setup(ah); @@ -651,13 +662,10 @@ static void ath9k_hw_init_cal_settings(struct ath_hw *ah) static void ath9k_hw_init_mode_regs(struct ath_hw *ah) { if (AR_SREV_9271(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271, - ARRAY_SIZE(ar9271Modes_9271), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271, - ARRAY_SIZE(ar9271Common_9271), 2); - INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only, - ar9271Modes_9271_1_0_only, - ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6); + INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271_1_0, + ARRAY_SIZE(ar9271Modes_9271_1_0), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271_1_0, + ARRAY_SIZE(ar9271Common_9271_1_0), 2); return; } @@ -949,14 +957,8 @@ int ath9k_hw_init(struct ath_hw *ah) ath9k_hw_init_cal_settings(ah); ah->ani_function = ATH9K_ANI_ALL; - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_10_OR_LATER(ah)) ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; - ah->ath9k_hw_rf_set_freq = &ath9k_hw_ar9280_set_channel; - ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_9280_spur_mitigate; - } else { - ah->ath9k_hw_rf_set_freq = &ath9k_hw_set_channel; - ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_spur_mitigate; - } ath9k_hw_init_mode_regs(ah); @@ -1035,22 +1037,6 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); } -static void ath9k_hw_change_target_baud(struct ath_hw *ah, u32 freq, u32 baud) -{ - u32 lcr; - u32 baud_divider = freq * 1000 * 1000 / 16 / baud; - - lcr = REG_READ(ah , 0x5100c); - lcr |= 0x80; - - REG_WRITE(ah, 0x5100c, lcr); - REG_WRITE(ah, 0x51004, (baud_divider >> 8)); - REG_WRITE(ah, 0x51000, (baud_divider & 0xff)); - - lcr &= ~0x80; - REG_WRITE(ah, 0x5100c, lcr); -} - static void ath9k_hw_init_pll(struct ath_hw *ah, struct ath9k_channel *chan) { @@ -1114,26 +1100,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, } REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); - /* Switch the core clock for ar9271 to 117Mhz */ - if (AR_SREV_9271(ah)) { - if ((pll == 0x142c) || (pll == 0x2850) ) { - udelay(500); - /* set CLKOBS to output AHB clock */ - REG_WRITE(ah, 0x7020, 0xe); - /* - * 0x304: 117Mhz, ahb_ratio: 1x1 - * 0x306: 40Mhz, ahb_ratio: 1x1 - */ - REG_WRITE(ah, 0x50040, 0x304); - /* - * makes adjustments for the baud dividor to keep the - * targetted baud rate based on the used core clock. - */ - ath9k_hw_change_target_baud(ah, AR9271_CORE_CLOCK, - AR9271_TARGET_BAUD_RATE); - } - } - udelay(RTC_PLL_SETTLE_DELAY); REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); @@ -1286,8 +1252,7 @@ void ath9k_hw_detach(struct ath_hw *ah) ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); free_hw: - if (!AR_SREV_9280_10_OR_LATER(ah)) - ath9k_hw_rf_free_ext_banks(ah); + ath9k_hw_rf_free(ah); kfree(ah); ah = NULL; } @@ -1309,8 +1274,7 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, * AR9271 1.1 */ if (AR_SREV_9271_10(ah)) { - val = REG_READ(ah, AR_PHY_SPECTRAL_SCAN) | - AR_PHY_SPECTRAL_SCAN_ENABLE; + val = REG_READ(ah, AR_PHY_SPECTRAL_SCAN) | AR_PHY_SPECTRAL_SCAN_ENABLE; REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); } else if (AR_SREV_9271_11(ah)) @@ -1525,11 +1489,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, DO_DELAY(regWrites); } - ath9k_hw_write_regs(ah, freqIndex, regWrites); - - if (AR_SREV_9271_10(ah)) - REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only, - modesIndex, regWrites); + ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites); if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, @@ -1872,7 +1832,6 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_channel *channel = chan->chan; u32 synthDelay, qnum; - int r; for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { if (ath9k_hw_numtxpending(ah, qnum)) { @@ -1893,11 +1852,14 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, ath9k_hw_set_regs(ah, chan); - r = ah->ath9k_hw_rf_set_freq(ah, chan); - if (r) { - ath_print(common, ATH_DBG_FATAL, - "Failed to set channel\n"); - return false; + if (AR_SREV_9280_10_OR_LATER(ah)) { + ath9k_hw_ar9280_set_channel(ah, chan); + } else { + if (!(ath9k_hw_set_channel(ah, chan))) { + ath_print(common, ATH_DBG_FATAL, + "Failed to set channel\n"); + return false; + } } ah->eep_ops->set_txpower(ah, chan, @@ -1920,7 +1882,10 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) ath9k_hw_set_delta_slope(ah, chan); - ah->ath9k_hw_spur_mitigate_freq(ah, chan); + if (AR_SREV_9280_10_OR_LATER(ah)) + ath9k_hw_9280_spur_mitigate(ah, chan); + else + ath9k_hw_spur_mitigate(ah, chan); if (!chan->oneTimeCalsDone) chan->oneTimeCalsDone = true; @@ -1928,6 +1893,457 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, return true; } +static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) +{ + int bb_spur = AR_NO_SPUR; + int freq; + int bin, cur_bin; + int bb_spur_off, spur_subchannel_sd; + int spur_freq_sd; + int spur_delta_phase; + int denominator; + int upper, lower, cur_vit_mask; + int tmp, newVal; + int i; + int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 + }; + int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 + }; + int inc[4] = { 0, 100, 0, 0 }; + struct chan_centers centers; + + int8_t mask_m[123]; + int8_t mask_p[123]; + int8_t mask_amt; + int tmp_mask; + int cur_bb_spur; + bool is2GHz = IS_CHAN_2GHZ(chan); + + memset(&mask_m, 0, sizeof(int8_t) * 123); + memset(&mask_p, 0, sizeof(int8_t) * 123); + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + freq = centers.synth_center; + + ah->config.spurmode = SPUR_ENABLE_EEPROM; + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { + cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); + + if (is2GHz) + cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; + else + cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; + + if (AR_NO_SPUR == cur_bb_spur) + break; + cur_bb_spur = cur_bb_spur - freq; + + if (IS_CHAN_HT40(chan)) { + if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && + (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { + bb_spur = cur_bb_spur; + break; + } + } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && + (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { + bb_spur = cur_bb_spur; + break; + } + } + + if (AR_NO_SPUR == bb_spur) { + REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, + AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); + return; + } else { + REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, + AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); + } + + bin = bb_spur * 320; + + tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); + + newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | + AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); + + newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | + AR_PHY_SPUR_REG_ENABLE_MASK_PPM | + AR_PHY_SPUR_REG_MASK_RATE_SELECT | + AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | + SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); + REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); + + if (IS_CHAN_HT40(chan)) { + if (bb_spur < 0) { + spur_subchannel_sd = 1; + bb_spur_off = bb_spur + 10; + } else { + spur_subchannel_sd = 0; + bb_spur_off = bb_spur - 10; + } + } else { + spur_subchannel_sd = 0; + bb_spur_off = bb_spur; + } + + if (IS_CHAN_HT40(chan)) + spur_delta_phase = + ((bb_spur * 262144) / + 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; + else + spur_delta_phase = + ((bb_spur * 524288) / + 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; + + denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; + spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; + + newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + REG_WRITE(ah, AR_PHY_TIMING11, newVal); + + newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; + REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); + + cur_bin = -6000; + upper = bin + 100; + lower = bin - 100; + + for (i = 0; i < 4; i++) { + int pilot_mask = 0; + int chan_mask = 0; + int bp = 0; + for (bp = 0; bp < 30; bp++) { + if ((cur_bin > lower) && (cur_bin < upper)) { + pilot_mask = pilot_mask | 0x1 << bp; + chan_mask = chan_mask | 0x1 << bp; + } + cur_bin += 100; + } + cur_bin += inc[i]; + REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); + REG_WRITE(ah, chan_mask_reg[i], chan_mask); + } + + cur_vit_mask = 6100; + upper = bin + 120; + lower = bin - 120; + + for (i = 0; i < 123; i++) { + if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + + /* workaround for gcc bug #37014 */ + volatile int tmp_v = abs(cur_vit_mask - bin); + + if (tmp_v < 75) + mask_amt = 1; + else + mask_amt = 0; + if (cur_vit_mask < 0) + mask_m[abs(cur_vit_mask / 100)] = mask_amt; + else + mask_p[cur_vit_mask / 100] = mask_amt; + } + cur_vit_mask -= 100; + } + + tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) + | (mask_m[48] << 26) | (mask_m[49] << 24) + | (mask_m[50] << 22) | (mask_m[51] << 20) + | (mask_m[52] << 18) | (mask_m[53] << 16) + | (mask_m[54] << 14) | (mask_m[55] << 12) + | (mask_m[56] << 10) | (mask_m[57] << 8) + | (mask_m[58] << 6) | (mask_m[59] << 4) + | (mask_m[60] << 2) | (mask_m[61] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); + REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + + tmp_mask = (mask_m[31] << 28) + | (mask_m[32] << 26) | (mask_m[33] << 24) + | (mask_m[34] << 22) | (mask_m[35] << 20) + | (mask_m[36] << 18) | (mask_m[37] << 16) + | (mask_m[48] << 14) | (mask_m[39] << 12) + | (mask_m[40] << 10) | (mask_m[41] << 8) + | (mask_m[42] << 6) | (mask_m[43] << 4) + | (mask_m[44] << 2) | (mask_m[45] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + + tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) + | (mask_m[18] << 26) | (mask_m[18] << 24) + | (mask_m[20] << 22) | (mask_m[20] << 20) + | (mask_m[22] << 18) | (mask_m[22] << 16) + | (mask_m[24] << 14) | (mask_m[24] << 12) + | (mask_m[25] << 10) | (mask_m[26] << 8) + | (mask_m[27] << 6) | (mask_m[28] << 4) + | (mask_m[29] << 2) | (mask_m[30] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + + tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) + | (mask_m[2] << 26) | (mask_m[3] << 24) + | (mask_m[4] << 22) | (mask_m[5] << 20) + | (mask_m[6] << 18) | (mask_m[7] << 16) + | (mask_m[8] << 14) | (mask_m[9] << 12) + | (mask_m[10] << 10) | (mask_m[11] << 8) + | (mask_m[12] << 6) | (mask_m[13] << 4) + | (mask_m[14] << 2) | (mask_m[15] << 0); + REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + + tmp_mask = (mask_p[15] << 28) + | (mask_p[14] << 26) | (mask_p[13] << 24) + | (mask_p[12] << 22) | (mask_p[11] << 20) + | (mask_p[10] << 18) | (mask_p[9] << 16) + | (mask_p[8] << 14) | (mask_p[7] << 12) + | (mask_p[6] << 10) | (mask_p[5] << 8) + | (mask_p[4] << 6) | (mask_p[3] << 4) + | (mask_p[2] << 2) | (mask_p[1] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + + tmp_mask = (mask_p[30] << 28) + | (mask_p[29] << 26) | (mask_p[28] << 24) + | (mask_p[27] << 22) | (mask_p[26] << 20) + | (mask_p[25] << 18) | (mask_p[24] << 16) + | (mask_p[23] << 14) | (mask_p[22] << 12) + | (mask_p[21] << 10) | (mask_p[20] << 8) + | (mask_p[19] << 6) | (mask_p[18] << 4) + | (mask_p[17] << 2) | (mask_p[16] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + + tmp_mask = (mask_p[45] << 28) + | (mask_p[44] << 26) | (mask_p[43] << 24) + | (mask_p[42] << 22) | (mask_p[41] << 20) + | (mask_p[40] << 18) | (mask_p[39] << 16) + | (mask_p[38] << 14) | (mask_p[37] << 12) + | (mask_p[36] << 10) | (mask_p[35] << 8) + | (mask_p[34] << 6) | (mask_p[33] << 4) + | (mask_p[32] << 2) | (mask_p[31] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + + tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) + | (mask_p[59] << 26) | (mask_p[58] << 24) + | (mask_p[57] << 22) | (mask_p[56] << 20) + | (mask_p[55] << 18) | (mask_p[54] << 16) + | (mask_p[53] << 14) | (mask_p[52] << 12) + | (mask_p[51] << 10) | (mask_p[50] << 8) + | (mask_p[49] << 6) | (mask_p[48] << 4) + | (mask_p[47] << 2) | (mask_p[46] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); +} + +static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) +{ + int bb_spur = AR_NO_SPUR; + int bin, cur_bin; + int spur_freq_sd; + int spur_delta_phase; + int denominator; + int upper, lower, cur_vit_mask; + int tmp, new; + int i; + int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 + }; + int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 + }; + int inc[4] = { 0, 100, 0, 0 }; + + int8_t mask_m[123]; + int8_t mask_p[123]; + int8_t mask_amt; + int tmp_mask; + int cur_bb_spur; + bool is2GHz = IS_CHAN_2GHZ(chan); + + memset(&mask_m, 0, sizeof(int8_t) * 123); + memset(&mask_p, 0, sizeof(int8_t) * 123); + + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { + cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); + if (AR_NO_SPUR == cur_bb_spur) + break; + cur_bb_spur = cur_bb_spur - (chan->channel * 10); + if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { + bb_spur = cur_bb_spur; + break; + } + } + + if (AR_NO_SPUR == bb_spur) + return; + + bin = bb_spur * 32; + + tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); + new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | + AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + + REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); + + new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | + AR_PHY_SPUR_REG_ENABLE_MASK_PPM | + AR_PHY_SPUR_REG_MASK_RATE_SELECT | + AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | + SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); + REG_WRITE(ah, AR_PHY_SPUR_REG, new); + + spur_delta_phase = ((bb_spur * 524288) / 100) & + AR_PHY_TIMING11_SPUR_DELTA_PHASE; + + denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; + spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; + + new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + REG_WRITE(ah, AR_PHY_TIMING11, new); + + cur_bin = -6000; + upper = bin + 100; + lower = bin - 100; + + for (i = 0; i < 4; i++) { + int pilot_mask = 0; + int chan_mask = 0; + int bp = 0; + for (bp = 0; bp < 30; bp++) { + if ((cur_bin > lower) && (cur_bin < upper)) { + pilot_mask = pilot_mask | 0x1 << bp; + chan_mask = chan_mask | 0x1 << bp; + } + cur_bin += 100; + } + cur_bin += inc[i]; + REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); + REG_WRITE(ah, chan_mask_reg[i], chan_mask); + } + + cur_vit_mask = 6100; + upper = bin + 120; + lower = bin - 120; + + for (i = 0; i < 123; i++) { + if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + + /* workaround for gcc bug #37014 */ + volatile int tmp_v = abs(cur_vit_mask - bin); + + if (tmp_v < 75) + mask_amt = 1; + else + mask_amt = 0; + if (cur_vit_mask < 0) + mask_m[abs(cur_vit_mask / 100)] = mask_amt; + else + mask_p[cur_vit_mask / 100] = mask_amt; + } + cur_vit_mask -= 100; + } + + tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) + | (mask_m[48] << 26) | (mask_m[49] << 24) + | (mask_m[50] << 22) | (mask_m[51] << 20) + | (mask_m[52] << 18) | (mask_m[53] << 16) + | (mask_m[54] << 14) | (mask_m[55] << 12) + | (mask_m[56] << 10) | (mask_m[57] << 8) + | (mask_m[58] << 6) | (mask_m[59] << 4) + | (mask_m[60] << 2) | (mask_m[61] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); + REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + + tmp_mask = (mask_m[31] << 28) + | (mask_m[32] << 26) | (mask_m[33] << 24) + | (mask_m[34] << 22) | (mask_m[35] << 20) + | (mask_m[36] << 18) | (mask_m[37] << 16) + | (mask_m[48] << 14) | (mask_m[39] << 12) + | (mask_m[40] << 10) | (mask_m[41] << 8) + | (mask_m[42] << 6) | (mask_m[43] << 4) + | (mask_m[44] << 2) | (mask_m[45] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + + tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) + | (mask_m[18] << 26) | (mask_m[18] << 24) + | (mask_m[20] << 22) | (mask_m[20] << 20) + | (mask_m[22] << 18) | (mask_m[22] << 16) + | (mask_m[24] << 14) | (mask_m[24] << 12) + | (mask_m[25] << 10) | (mask_m[26] << 8) + | (mask_m[27] << 6) | (mask_m[28] << 4) + | (mask_m[29] << 2) | (mask_m[30] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + + tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) + | (mask_m[2] << 26) | (mask_m[3] << 24) + | (mask_m[4] << 22) | (mask_m[5] << 20) + | (mask_m[6] << 18) | (mask_m[7] << 16) + | (mask_m[8] << 14) | (mask_m[9] << 12) + | (mask_m[10] << 10) | (mask_m[11] << 8) + | (mask_m[12] << 6) | (mask_m[13] << 4) + | (mask_m[14] << 2) | (mask_m[15] << 0); + REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + + tmp_mask = (mask_p[15] << 28) + | (mask_p[14] << 26) | (mask_p[13] << 24) + | (mask_p[12] << 22) | (mask_p[11] << 20) + | (mask_p[10] << 18) | (mask_p[9] << 16) + | (mask_p[8] << 14) | (mask_p[7] << 12) + | (mask_p[6] << 10) | (mask_p[5] << 8) + | (mask_p[4] << 6) | (mask_p[3] << 4) + | (mask_p[2] << 2) | (mask_p[1] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + + tmp_mask = (mask_p[30] << 28) + | (mask_p[29] << 26) | (mask_p[28] << 24) + | (mask_p[27] << 22) | (mask_p[26] << 20) + | (mask_p[25] << 18) | (mask_p[24] << 16) + | (mask_p[23] << 14) | (mask_p[22] << 12) + | (mask_p[21] << 10) | (mask_p[20] << 8) + | (mask_p[19] << 6) | (mask_p[18] << 4) + | (mask_p[17] << 2) | (mask_p[16] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + + tmp_mask = (mask_p[45] << 28) + | (mask_p[44] << 26) | (mask_p[43] << 24) + | (mask_p[42] << 22) | (mask_p[41] << 20) + | (mask_p[40] << 18) | (mask_p[39] << 16) + | (mask_p[38] << 14) | (mask_p[37] << 12) + | (mask_p[36] << 10) | (mask_p[35] << 8) + | (mask_p[34] << 6) | (mask_p[33] << 4) + | (mask_p[32] << 2) | (mask_p[31] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + + tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) + | (mask_p[59] << 26) | (mask_p[58] << 24) + | (mask_p[57] << 22) | (mask_p[56] << 20) + | (mask_p[55] << 18) | (mask_p[54] << 16) + | (mask_p[53] << 14) | (mask_p[52] << 12) + | (mask_p[51] << 10) | (mask_p[50] << 8) + | (mask_p[49] << 6) | (mask_p[48] << 4) + | (mask_p[47] << 2) | (mask_p[46] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); +} + static void ath9k_enable_rfkill(struct ath_hw *ah) { REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, @@ -2053,11 +2469,14 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) ath9k_hw_set_delta_slope(ah, chan); - ah->ath9k_hw_spur_mitigate_freq(ah, chan); + if (AR_SREV_9280_10_OR_LATER(ah)) + ath9k_hw_9280_spur_mitigate(ah, chan); + else + ath9k_hw_spur_mitigate(ah, chan); + ah->eep_ops->set_board_values(ah, chan); - if (AR_SREV_5416(ah)) - ath9k_hw_decrease_chain_power(ah, chan); + ath9k_hw_decrease_chain_power(ah, chan); REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) @@ -2078,9 +2497,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); - r = ah->ath9k_hw_rf_set_freq(ah, chan); - if (r) - return r; + if (AR_SREV_9280_10_OR_LATER(ah)) + ath9k_hw_ar9280_set_channel(ah, chan); + else + if (!(ath9k_hw_set_channel(ah, chan))) + return -EIO; for (i = 0; i < AR_NUM_DCU; i++) REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); @@ -3929,89 +4350,3 @@ void ath_gen_timer_isr(struct ath_hw *ah) } } EXPORT_SYMBOL(ath_gen_timer_isr); - -static struct { - u32 version; - const char * name; -} ath_mac_bb_names[] = { - /* Devices with external radios */ - { AR_SREV_VERSION_5416_PCI, "5416" }, - { AR_SREV_VERSION_5416_PCIE, "5418" }, - { AR_SREV_VERSION_9100, "9100" }, - { AR_SREV_VERSION_9160, "9160" }, - /* Single-chip solutions */ - { AR_SREV_VERSION_9280, "9280" }, - { AR_SREV_VERSION_9285, "9285" }, - { AR_SREV_VERSION_9287, "9287" }, - { AR_SREV_VERSION_9271, "9271" }, -}; - -/* For devices with external radios */ -static struct { - u16 version; - const char * name; -} ath_rf_names[] = { - { 0, "5133" }, - { AR_RAD5133_SREV_MAJOR, "5133" }, - { AR_RAD5122_SREV_MAJOR, "5122" }, - { AR_RAD2133_SREV_MAJOR, "2133" }, - { AR_RAD2122_SREV_MAJOR, "2122" } -}; - -/* - * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown. - */ -static const char *ath9k_hw_mac_bb_name(u32 mac_bb_version) -{ - int i; - - for (i=0; i= AR9280 are single-chip */ - if (AR_SREV_9280_10_OR_LATER(ah)) { - used = snprintf(hw_name, len, - "Atheros AR%s Rev:%x", - ath9k_hw_mac_bb_name(ah->hw_version.macVersion), - ah->hw_version.macRev); - } - else { - used = snprintf(hw_name, len, - "Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x", - ath9k_hw_mac_bb_name(ah->hw_version.macVersion), - ah->hw_version.macRev, - ath9k_hw_rf_name((ah->hw_version.analog5GhzRev & - AR_RADIO_SREV_MAJOR)), - ah->hw_version.phyRev); - } - - hw_name[used] = '\0'; -} -EXPORT_SYMBOL(ath9k_hw_name); diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.h b/trunk/drivers/net/wireless/ath/ath9k/hw.h index c7b0c4d5f75a..cdaec526db35 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.h @@ -148,15 +148,6 @@ enum wireless_mode { ATH9K_MODE_MAX, }; -/** - * ath9k_ant_setting - transmit antenna settings - * - * Configures the antenna setting to use for transmit. - * - * @ATH9K_ANT_VARIABLE: this means transmit on all active antennas - * @ATH9K_ANT_FIXED_A: this means transmit on the first antenna only - * @ATH9K_ANT_FIXED_B: this means transmit on the second antenna only - */ enum ath9k_ant_setting { ATH9K_ANT_VARIABLE = 0, ATH9K_ANT_FIXED_A, @@ -548,14 +539,7 @@ struct ath_hw { DONT_USE_32KHZ, } enable_32kHz_clock; - /* Callback for radio frequency change */ - int (*ath9k_hw_rf_set_freq)(struct ath_hw *ah, struct ath9k_channel *chan); - - /* Callback for baseband spur frequency */ - void (*ath9k_hw_spur_mitigate_freq)(struct ath_hw *ah, - struct ath9k_channel *chan); - - /* Used to program the radio on non single-chip devices */ + /* RF */ u32 *analogBank0Data; u32 *analogBank1Data; u32 *analogBank2Data; @@ -612,7 +596,6 @@ struct ath_hw { struct ar5416IniArray iniModesAdditional; struct ar5416IniArray iniModesRxGain; struct ar5416IniArray iniModesTxGain; - struct ar5416IniArray iniModes_9271_1_0_only; struct ar5416IniArray iniCckfirNormal; struct ar5416IniArray iniCckfirJapan2484; @@ -635,6 +618,7 @@ static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah) const char *ath9k_hw_probe(u16 vendorid, u16 devid); void ath9k_hw_detach(struct ath_hw *ah); int ath9k_hw_init(struct ath_hw *ah); +void ath9k_hw_rf_free(struct ath_hw *ah); int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, bool bChannelChange); void ath9k_hw_fill_cap_info(struct ath_hw *ah); @@ -720,8 +704,6 @@ void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); void ath_gen_timer_isr(struct ath_hw *hw); u32 ath9k_hw_gettsf32(struct ath_hw *ah); -void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len); - #define ATH_PCIE_CAP_LINK_CTRL 0x70 #define ATH_PCIE_CAP_LINK_L0S 1 #define ATH_PCIE_CAP_LINK_L1 2 diff --git a/trunk/drivers/net/wireless/ath/ath9k/initvals.h b/trunk/drivers/net/wireless/ath/ath9k/initvals.h index 8a3bf3ab998d..3ee6658d809b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/initvals.h +++ b/trunk/drivers/net/wireless/ath/ath9k/initvals.h @@ -6379,8 +6379,8 @@ static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { }; -/* AR9271 initialization values automaticaly created: 06/04/09 */ -static const u_int32_t ar9271Modes_9271[][6] = { +/* AR9271 initialization values automaticaly created: 03/23/09 */ +static const u_int32_t ar9271Modes_9271_1_0[][6] = { { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, @@ -6390,8 +6390,8 @@ static const u_int32_t ar9271Modes_9271[][6] = { { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e }, - { 0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001 }, + { 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 }, @@ -6405,7 +6405,6 @@ static const u_int32_t ar9271Modes_9271[][6] = { { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310, 0x30002310 }, { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, @@ -6416,7 +6415,7 @@ static const u_int32_t ar9271Modes_9271[][6] = { { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f }, + { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 }, { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, @@ -6705,7 +6704,7 @@ static const u_int32_t ar9271Modes_9271[][6] = { { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, }; -static const u_int32_t ar9271Common_9271[][2] = { +static const u_int32_t ar9271Common_9271_1_0[][2] = { { 0x0000000c, 0x00000000 }, { 0x00000030, 0x00020045 }, { 0x00000034, 0x00000005 }, @@ -6801,7 +6800,7 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x0000803c, 0x00000000 }, { 0x00008048, 0x00000000 }, { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, + { 0x00008058, 0x02000000 }, { 0x0000805c, 0x000fc78f }, { 0x00008060, 0x0000000f }, { 0x00008064, 0x00000000 }, @@ -6832,7 +6831,7 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x00008110, 0x00000168 }, { 0x00008118, 0x000100aa }, { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04810 }, + { 0x00008120, 0x08f04814 }, { 0x00008124, 0x00000000 }, { 0x00008128, 0x00000000 }, { 0x0000812c, 0x00000000 }, @@ -6879,7 +6878,7 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x00008258, 0x00000000 }, { 0x0000825c, 0x400000ff }, { 0x00008260, 0x00080922 }, - { 0x00008264, 0x88a00010 }, + { 0x00008264, 0xa8a00010 }, { 0x00008270, 0x00000000 }, { 0x00008274, 0x40000000 }, { 0x00008278, 0x003e4180 }, @@ -6911,7 +6910,7 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x00007814, 0x924934a8 }, { 0x0000781c, 0x00000000 }, { 0x00007820, 0x00000c04 }, - { 0x00007824, 0x00d8abff }, + { 0x00007824, 0x00d86bff }, { 0x00007828, 0x66964300 }, { 0x0000782c, 0x8db6d961 }, { 0x00007830, 0x8db6d96c }, @@ -6945,6 +6944,7 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x00009904, 0x00000000 }, { 0x00009908, 0x00000000 }, { 0x0000990c, 0x00000000 }, + { 0x00009910, 0x30002310 }, { 0x0000991c, 0x10000fff }, { 0x00009920, 0x04900000 }, { 0x00009928, 0x00000001 }, @@ -6958,7 +6958,7 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x00009954, 0x5f3ca3de }, { 0x00009958, 0x0108ecff }, { 0x00009968, 0x000003ce }, - { 0x00009970, 0x192bb514 }, + { 0x00009970, 0x192bb515 }, { 0x00009974, 0x00000000 }, { 0x00009978, 0x00000001 }, { 0x0000997c, 0x00000000 }, @@ -7045,8 +7045,3 @@ static const u_int32_t ar9271Common_9271[][2] = { { 0x0000d380, 0x7f3c7bba }, { 0x0000d384, 0xf3307ff0 }, }; - -static const u_int32_t ar9271Modes_9271_1_0_only[][6] = { - { 0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311 }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, -}; diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index 9fefc51aec17..69cf702b18c2 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -3191,6 +3191,64 @@ struct ieee80211_ops ath9k_ops = { .rfkill_poll = ath9k_rfkill_poll_state, }; +static struct { + u32 version; + const char * name; +} ath_mac_bb_names[] = { + { AR_SREV_VERSION_5416_PCI, "5416" }, + { AR_SREV_VERSION_5416_PCIE, "5418" }, + { AR_SREV_VERSION_9100, "9100" }, + { AR_SREV_VERSION_9160, "9160" }, + { AR_SREV_VERSION_9280, "9280" }, + { AR_SREV_VERSION_9285, "9285" }, + { AR_SREV_VERSION_9287, "9287" } +}; + +static struct { + u16 version; + const char * name; +} ath_rf_names[] = { + { 0, "5133" }, + { AR_RAD5133_SREV_MAJOR, "5133" }, + { AR_RAD5122_SREV_MAJOR, "5122" }, + { AR_RAD2133_SREV_MAJOR, "2133" }, + { AR_RAD2122_SREV_MAJOR, "2122" } +}; + +/* + * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown. + */ +const char * +ath_mac_bb_name(u32 mac_bb_version) +{ + int i; + + for (i=0; iirq = pdev->irq; ah = sc->sc_ah; - ath9k_hw_name(ah, hw_name, sizeof(hw_name)); printk(KERN_INFO - "%s: %s mem=0x%lx, irq=%d\n", + "%s: Atheros AR%s MAC/BB Rev:%x " + "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n", wiphy_name(hw->wiphy), - hw_name, + ath_mac_bb_name(ah->hw_version.macVersion), + ah->hw_version.macRev, + ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)), + ah->hw_version.phyRev, (unsigned long)mem, pdev->irq); return 0; diff --git a/trunk/drivers/net/wireless/ath/ath9k/phy.c b/trunk/drivers/net/wireless/ath/ath9k/phy.c index 13ab4d7eb7aa..72a17c43a5a0 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/phy.c +++ b/trunk/drivers/net/wireless/ath/ath9k/phy.c @@ -14,70 +14,91 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/** - * DOC: Programming Atheros 802.11n analog front end radios - * - * AR5416 MAC based PCI devices and AR518 MAC based PCI-Express - * devices have either an external AR2133 analog front end radio for single - * band 2.4 GHz communication or an AR5133 analog front end radio for dual - * band 2.4 GHz / 5 GHz communication. - * - * All devices after the AR5416 and AR5418 family starting with the AR9280 - * have their analog front radios, MAC/BB and host PCIe/USB interface embedded - * into a single-chip and require less programming. - * - * The following single-chips exist with a respective embedded radio: - * - * AR9280 - 11n dual-band 2x2 MIMO for PCIe - * AR9281 - 11n single-band 1x2 MIMO for PCIe - * AR9285 - 11n single-band 1x1 for PCIe - * AR9287 - 11n single-band 2x2 MIMO for PCIe - * - * AR9220 - 11n dual-band 2x2 MIMO for PCI - * AR9223 - 11n single-band 2x2 MIMO for PCI - * - * AR9287 - 11n single-band 1x1 MIMO for USB - */ - #include "hw.h" -/** - * ath9k_hw_write_regs - ?? - * - * @ah: atheros hardware structure - * @freqIndex: - * @regWrites: - * - * Used for both the chipsets with an external AR2133/AR5133 radios and - * single-chip devices. - */ -void ath9k_hw_write_regs(struct ath_hw *ah, u32 freqIndex, int regWrites) +void +ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex, + int regWrites) { REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); } -/** - * ath9k_hw_ar9280_set_channel - set channel on single-chip device - * @ah: atheros hardware structure - * @chan: - * - * This is the function to change channel on single-chip devices, that is - * all devices after ar9280. - * - * This function takes the channel value in MHz and sets - * hardware channel value. Assumes writes have been enabled to analog bus. - * - * Actual Expression, - * - * For 2GHz channel, - * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) - * (freq_ref = 40MHz) - * - * For 5GHz channel, - * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) - * (freq_ref = 40MHz/(24>>amodeRefSel)) - */ -int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) +bool +ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) +{ + struct ath_common *common = ath9k_hw_common(ah); + u32 channelSel = 0; + u32 bModeSynth = 0; + u32 aModeRefSel = 0; + u32 reg32 = 0; + u16 freq; + struct chan_centers centers; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + freq = centers.synth_center; + + if (freq < 4800) { + u32 txctl; + + if (((freq - 2192) % 5) == 0) { + channelSel = ((freq - 672) * 2 - 3040) / 10; + bModeSynth = 0; + } else if (((freq - 2224) % 5) == 0) { + channelSel = ((freq - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + ath_print(common, ATH_DBG_FATAL, + "Invalid channel %u MHz\n", freq); + return false; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath9k_hw_reverse_bits(channelSel, 8); + + txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + + REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); + } + + } else if ((freq % 20) == 0 && freq >= 5120) { + channelSel = + ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); + aModeRefSel = ath9k_hw_reverse_bits(1, 2); + } else if ((freq % 10) == 0) { + channelSel = + ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); + if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) + aModeRefSel = ath9k_hw_reverse_bits(2, 2); + else + aModeRefSel = ath9k_hw_reverse_bits(1, 2); + } else if ((freq % 5) == 0) { + channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); + aModeRefSel = ath9k_hw_reverse_bits(1, 2); + } else { + ath_print(common, ATH_DBG_FATAL, + "Invalid channel %u MHz\n", freq); + return false; + } + + reg32 = + (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 5) | 0x1; + + REG_WRITE(ah, AR_PHY(0x37), reg32); + + ah->curchan = chan; + ah->curchan_rad_index = -1; + + return true; +} + +void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, + struct ath9k_channel *chan) { u16 bMode, fracMode, aModeRefSel = 0; u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; @@ -90,7 +111,7 @@ int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); reg32 &= 0xc0000000; - if (freq < 4800) { /* 2 GHz, fractional mode */ + if (freq < 4800) { u32 txctl; int regWrites = 0; @@ -101,7 +122,6 @@ int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) if (AR_SREV_9287_11_OR_LATER(ah)) { if (freq == 2484) { - /* Enable channel spreading for channel 14 */ REG_WRITE_ARRAY(&ah->iniCckfirJapan2484, 1, regWrites); } else { @@ -135,15 +155,10 @@ int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) case 1: default: aModeRefSel = 0; - /* - * Enable 2G (fractional) mode for channels - * which are 5MHz spaced. - */ fracMode = 1; refDivA = 1; channelSel = (freq * 0x8000) / 15; - /* RefDivA setting */ REG_RMW_FIELD(ah, AR_AN_SYNTH9, AR_AN_SYNTH9_REFDIVA, refDivA); @@ -165,284 +180,12 @@ int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) ah->curchan = chan; ah->curchan_rad_index = -1; - - return 0; -} - -/** - * ath9k_hw_9280_spur_mitigate - convert baseband spur frequency - * @ah: atheros hardware structure - * @chan: - * - * For single-chip solutions. Converts to baseband spur frequency given the - * input channel frequency and compute register settings below. - */ -void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int bb_spur = AR_NO_SPUR; - int freq; - int bin, cur_bin; - int bb_spur_off, spur_subchannel_sd; - int spur_freq_sd; - int spur_delta_phase; - int denominator; - int upper, lower, cur_vit_mask; - int tmp, newVal; - int i; - int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, - AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 - }; - int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, - AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 - }; - int inc[4] = { 0, 100, 0, 0 }; - struct chan_centers centers; - - int8_t mask_m[123]; - int8_t mask_p[123]; - int8_t mask_amt; - int tmp_mask; - int cur_bb_spur; - bool is2GHz = IS_CHAN_2GHZ(chan); - - memset(&mask_m, 0, sizeof(int8_t) * 123); - memset(&mask_p, 0, sizeof(int8_t) * 123); - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = centers.synth_center; - - ah->config.spurmode = SPUR_ENABLE_EEPROM; - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); - - if (is2GHz) - cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; - else - cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; - - if (AR_NO_SPUR == cur_bb_spur) - break; - cur_bb_spur = cur_bb_spur - freq; - - if (IS_CHAN_HT40(chan)) { - if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && - (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { - bb_spur = cur_bb_spur; - break; - } - } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && - (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { - bb_spur = cur_bb_spur; - break; - } - } - - if (AR_NO_SPUR == bb_spur) { - REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, - AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); - return; - } else { - REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, - AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); - } - - bin = bb_spur * 320; - - tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); - - newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | - AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | - AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | - AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); - - newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | - AR_PHY_SPUR_REG_ENABLE_MASK_PPM | - AR_PHY_SPUR_REG_MASK_RATE_SELECT | - AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | - SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); - REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); - - if (IS_CHAN_HT40(chan)) { - if (bb_spur < 0) { - spur_subchannel_sd = 1; - bb_spur_off = bb_spur + 10; - } else { - spur_subchannel_sd = 0; - bb_spur_off = bb_spur - 10; - } - } else { - spur_subchannel_sd = 0; - bb_spur_off = bb_spur; - } - - if (IS_CHAN_HT40(chan)) - spur_delta_phase = - ((bb_spur * 262144) / - 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; - else - spur_delta_phase = - ((bb_spur * 524288) / - 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; - - denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; - spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; - - newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | - SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | - SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); - REG_WRITE(ah, AR_PHY_TIMING11, newVal); - - newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; - REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); - - cur_bin = -6000; - upper = bin + 100; - lower = bin - 100; - - for (i = 0; i < 4; i++) { - int pilot_mask = 0; - int chan_mask = 0; - int bp = 0; - for (bp = 0; bp < 30; bp++) { - if ((cur_bin > lower) && (cur_bin < upper)) { - pilot_mask = pilot_mask | 0x1 << bp; - chan_mask = chan_mask | 0x1 << bp; - } - cur_bin += 100; - } - cur_bin += inc[i]; - REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); - REG_WRITE(ah, chan_mask_reg[i], chan_mask); - } - - cur_vit_mask = 6100; - upper = bin + 120; - lower = bin - 120; - - for (i = 0; i < 123; i++) { - if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - - /* workaround for gcc bug #37014 */ - volatile int tmp_v = abs(cur_vit_mask - bin); - - if (tmp_v < 75) - mask_amt = 1; - else - mask_amt = 0; - if (cur_vit_mask < 0) - mask_m[abs(cur_vit_mask / 100)] = mask_amt; - else - mask_p[cur_vit_mask / 100] = mask_amt; - } - cur_vit_mask -= 100; - } - - tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) - | (mask_m[48] << 26) | (mask_m[49] << 24) - | (mask_m[50] << 22) | (mask_m[51] << 20) - | (mask_m[52] << 18) | (mask_m[53] << 16) - | (mask_m[54] << 14) | (mask_m[55] << 12) - | (mask_m[56] << 10) | (mask_m[57] << 8) - | (mask_m[58] << 6) | (mask_m[59] << 4) - | (mask_m[60] << 2) | (mask_m[61] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); - REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); - - tmp_mask = (mask_m[31] << 28) - | (mask_m[32] << 26) | (mask_m[33] << 24) - | (mask_m[34] << 22) | (mask_m[35] << 20) - | (mask_m[36] << 18) | (mask_m[37] << 16) - | (mask_m[48] << 14) | (mask_m[39] << 12) - | (mask_m[40] << 10) | (mask_m[41] << 8) - | (mask_m[42] << 6) | (mask_m[43] << 4) - | (mask_m[44] << 2) | (mask_m[45] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); - - tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) - | (mask_m[18] << 26) | (mask_m[18] << 24) - | (mask_m[20] << 22) | (mask_m[20] << 20) - | (mask_m[22] << 18) | (mask_m[22] << 16) - | (mask_m[24] << 14) | (mask_m[24] << 12) - | (mask_m[25] << 10) | (mask_m[26] << 8) - | (mask_m[27] << 6) | (mask_m[28] << 4) - | (mask_m[29] << 2) | (mask_m[30] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); - - tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) - | (mask_m[2] << 26) | (mask_m[3] << 24) - | (mask_m[4] << 22) | (mask_m[5] << 20) - | (mask_m[6] << 18) | (mask_m[7] << 16) - | (mask_m[8] << 14) | (mask_m[9] << 12) - | (mask_m[10] << 10) | (mask_m[11] << 8) - | (mask_m[12] << 6) | (mask_m[13] << 4) - | (mask_m[14] << 2) | (mask_m[15] << 0); - REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); - - tmp_mask = (mask_p[15] << 28) - | (mask_p[14] << 26) | (mask_p[13] << 24) - | (mask_p[12] << 22) | (mask_p[11] << 20) - | (mask_p[10] << 18) | (mask_p[9] << 16) - | (mask_p[8] << 14) | (mask_p[7] << 12) - | (mask_p[6] << 10) | (mask_p[5] << 8) - | (mask_p[4] << 6) | (mask_p[3] << 4) - | (mask_p[2] << 2) | (mask_p[1] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); - - tmp_mask = (mask_p[30] << 28) - | (mask_p[29] << 26) | (mask_p[28] << 24) - | (mask_p[27] << 22) | (mask_p[26] << 20) - | (mask_p[25] << 18) | (mask_p[24] << 16) - | (mask_p[23] << 14) | (mask_p[22] << 12) - | (mask_p[21] << 10) | (mask_p[20] << 8) - | (mask_p[19] << 6) | (mask_p[18] << 4) - | (mask_p[17] << 2) | (mask_p[16] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); - - tmp_mask = (mask_p[45] << 28) - | (mask_p[44] << 26) | (mask_p[43] << 24) - | (mask_p[42] << 22) | (mask_p[41] << 20) - | (mask_p[40] << 18) | (mask_p[39] << 16) - | (mask_p[38] << 14) | (mask_p[37] << 12) - | (mask_p[36] << 10) | (mask_p[35] << 8) - | (mask_p[34] << 6) | (mask_p[33] << 4) - | (mask_p[32] << 2) | (mask_p[31] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); - - tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) - | (mask_p[59] << 26) | (mask_p[58] << 24) - | (mask_p[57] << 22) | (mask_p[56] << 20) - | (mask_p[55] << 18) | (mask_p[54] << 16) - | (mask_p[53] << 14) | (mask_p[52] << 12) - | (mask_p[51] << 10) | (mask_p[50] << 8) - | (mask_p[49] << 6) | (mask_p[48] << 4) - | (mask_p[47] << 2) | (mask_p[46] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); } -/* All code below is for non single-chip solutions */ - -/** - * ath9k_phy_modify_rx_buffer() - perform analog swizzling of parameters - * @rfbuf: - * @reg32: - * @numBits: - * @firstBit: - * @column: - * - * Performs analog "swizzling" of parameters into their location. - * Used on external AR2133/AR5133 radios. - */ -static void ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, - u32 numBits, u32 firstBit, - u32 column) +static void +ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, + u32 numBits, u32 firstBit, + u32 column) { u32 tmp32, mask, arrayEntry, lastBit; int32_t bitPosition, bitsLeft; @@ -466,556 +209,26 @@ static void ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, } } -/* - * Fix on 2.4 GHz band for orientation sensitivity issue by increasing - * rf_pwd_icsyndiv. - * - * Theoretical Rules: - * if 2 GHz band - * if forceBiasAuto - * if synth_freq < 2412 - * bias = 0 - * else if 2412 <= synth_freq <= 2422 - * bias = 1 - * else // synth_freq > 2422 - * bias = 2 - * else if forceBias > 0 - * bias = forceBias & 7 - * else - * no change, use value from ini file - * else - * no change, invalid band - * - * 1st Mod: - * 2422 also uses value of 2 - * - * - * 2nd Mod: - * Less than 2412 uses value of 0, 2412 and above uses value of 2 - */ -static void ath9k_hw_force_bias(struct ath_hw *ah, u16 synth_freq) -{ - struct ath_common *common = ath9k_hw_common(ah); - u32 tmp_reg; - int reg_writes = 0; - u32 new_bias = 0; - - if (!AR_SREV_5416(ah) || synth_freq >= 3000) { - return; - } - - BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); - - if (synth_freq < 2412) - new_bias = 0; - else if (synth_freq < 2422) - new_bias = 1; - else - new_bias = 2; - - /* pre-reverse this field */ - tmp_reg = ath9k_hw_reverse_bits(new_bias, 3); - - ath_print(common, ATH_DBG_CONFIG, - "Force rf_pwd_icsyndiv to %1d on %4d\n", - new_bias, synth_freq); - - /* swizzle rf_pwd_icsyndiv */ - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3); - - /* write Bank 6 with new params */ - REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes); -} - -/** - * ath9k_hw_decrease_chain_power() - * - * @ah: atheros hardware structure - * @chan: - * - * Only used on the AR5416 and AR5418 with the external AR2133/AR5133 radios. - * - * Sets a chain internal RF path to the lowest output power. Any - * further writes to bank6 after this setting will override these - * changes. Thus this function must be the last function in the - * sequence to modify bank 6. - * - * This function must be called after ar5416SetRfRegs() which is - * called from ath9k_hw_process_ini() due to swizzling of bank 6. - * Depends on ah->analogBank6Data being initialized by - * ath9k_hw_set_rf_regs() - * - * Additional additive reduction in power - - * change chain's switch table so chain's tx state is actually the rx - * state value. May produce different results in 2GHz/5GHz as well as - * board to board but in general should be a reduction. - * - * Activated by #ifdef ALTER_SWITCH. Not tried yet. If so, must be - * called after ah->eep_ops->set_board_values() due to RMW of - * PHY_SWITCH_CHAIN_0. - */ -void ath9k_hw_decrease_chain_power(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - int i, regWrites = 0; - u32 bank6SelMask; - u32 *bank6Temp = ah->bank6Temp; - - BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); - - switch (ah->config.diversity_control) { - case ATH9K_ANT_FIXED_A: - bank6SelMask = - (ah->config.antenna_switch_swap & ANTSWAP_AB) ? - REDUCE_CHAIN_0 : /* swapped, reduce chain 0 */ - REDUCE_CHAIN_1; /* normal, select chain 1/2 to reduce */ - break; - case ATH9K_ANT_FIXED_B: - bank6SelMask = - (ah->config.antenna_switch_swap & ANTSWAP_AB) ? - REDUCE_CHAIN_1 : /* swapped, reduce chain 1/2 */ - REDUCE_CHAIN_0; /* normal, select chain 0 to reduce */ - break; - case ATH9K_ANT_VARIABLE: - return; /* do not change anything */ - break; - default: - return; /* do not change anything */ - break; - } - - for (i = 0; i < ah->iniBank6.ia_rows; i++) - bank6Temp[i] = ah->analogBank6Data[i]; - - /* Write Bank 5 to switch Bank 6 write to selected chain only */ - REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask); - - /* - * Modify Bank6 selected chain to use lowest amplification. - * Modifies the parameters to a value of 1. - * Depends on existing bank 6 values to be cached in - * ah->analogBank6Data - */ - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0); - - REG_WRITE_RF_ARRAY(&ah->iniBank6, bank6Temp, regWrites); - - REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053); -#ifdef ALTER_SWITCH - REG_WRITE(ah, PHY_SWITCH_CHAIN_0, - (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38) - | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38)); -#endif -} - -/** - * ath9k_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios - * @ah: atheros hardware stucture - * @chan: - * - * For the external AR2133/AR5133 radios, takes the MHz channel value and set - * the channel value. Assumes writes enabled to analog bus and bank6 register - * cache in ah->analogBank6Data. - */ -int ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) -{ - struct ath_common *common = ath9k_hw_common(ah); - u32 channelSel = 0; - u32 bModeSynth = 0; - u32 aModeRefSel = 0; - u32 reg32 = 0; - u16 freq; - struct chan_centers centers; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = centers.synth_center; - - if (freq < 4800) { - u32 txctl; - - if (((freq - 2192) % 5) == 0) { - channelSel = ((freq - 672) * 2 - 3040) / 10; - bModeSynth = 0; - } else if (((freq - 2224) % 5) == 0) { - channelSel = ((freq - 704) * 2 - 3040) / 10; - bModeSynth = 1; - } else { - ath_print(common, ATH_DBG_FATAL, - "Invalid channel %u MHz\n", freq); - return -EINVAL; - } - - channelSel = (channelSel << 2) & 0xff; - channelSel = ath9k_hw_reverse_bits(channelSel, 8); - - txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); - if (freq == 2484) { - - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl | AR_PHY_CCK_TX_CTRL_JAPAN); - } else { - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); - } - - } else if ((freq % 20) == 0 && freq >= 5120) { - channelSel = - ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else if ((freq % 10) == 0) { - channelSel = - ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); - if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) - aModeRefSel = ath9k_hw_reverse_bits(2, 2); - else - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else if ((freq % 5) == 0) { - channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else { - ath_print(common, ATH_DBG_FATAL, - "Invalid channel %u MHz\n", freq); - return -EINVAL; - } - - ath9k_hw_force_bias(ah, freq); - ath9k_hw_decrease_chain_power(ah, chan); - - reg32 = - (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | - (1 << 5) | 0x1; - - REG_WRITE(ah, AR_PHY(0x37), reg32); - - ah->curchan = chan; - ah->curchan_rad_index = -1; - - return 0; -} - -/** - * ath9k_hw_spur_mitigate - convert baseband spur frequency for external radios - * @ah: atheros hardware structure - * @chan: - * - * For non single-chip solutions. Converts to baseband spur frequency given the - * input channel frequency and compute register settings below. - */ -void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int bb_spur = AR_NO_SPUR; - int bin, cur_bin; - int spur_freq_sd; - int spur_delta_phase; - int denominator; - int upper, lower, cur_vit_mask; - int tmp, new; - int i; - int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, - AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 - }; - int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, - AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 - }; - int inc[4] = { 0, 100, 0, 0 }; - - int8_t mask_m[123]; - int8_t mask_p[123]; - int8_t mask_amt; - int tmp_mask; - int cur_bb_spur; - bool is2GHz = IS_CHAN_2GHZ(chan); - - memset(&mask_m, 0, sizeof(int8_t) * 123); - memset(&mask_p, 0, sizeof(int8_t) * 123); - - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); - if (AR_NO_SPUR == cur_bb_spur) - break; - cur_bb_spur = cur_bb_spur - (chan->channel * 10); - if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { - bb_spur = cur_bb_spur; - break; - } - } - - if (AR_NO_SPUR == bb_spur) - return; - - bin = bb_spur * 32; - - tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); - new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | - AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | - AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | - AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); - - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); - - new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | - AR_PHY_SPUR_REG_ENABLE_MASK_PPM | - AR_PHY_SPUR_REG_MASK_RATE_SELECT | - AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | - SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); - REG_WRITE(ah, AR_PHY_SPUR_REG, new); - - spur_delta_phase = ((bb_spur * 524288) / 100) & - AR_PHY_TIMING11_SPUR_DELTA_PHASE; - - denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; - spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; - - new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | - SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | - SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); - REG_WRITE(ah, AR_PHY_TIMING11, new); - - cur_bin = -6000; - upper = bin + 100; - lower = bin - 100; - - for (i = 0; i < 4; i++) { - int pilot_mask = 0; - int chan_mask = 0; - int bp = 0; - for (bp = 0; bp < 30; bp++) { - if ((cur_bin > lower) && (cur_bin < upper)) { - pilot_mask = pilot_mask | 0x1 << bp; - chan_mask = chan_mask | 0x1 << bp; - } - cur_bin += 100; - } - cur_bin += inc[i]; - REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); - REG_WRITE(ah, chan_mask_reg[i], chan_mask); - } - - cur_vit_mask = 6100; - upper = bin + 120; - lower = bin - 120; - - for (i = 0; i < 123; i++) { - if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - - /* workaround for gcc bug #37014 */ - volatile int tmp_v = abs(cur_vit_mask - bin); - - if (tmp_v < 75) - mask_amt = 1; - else - mask_amt = 0; - if (cur_vit_mask < 0) - mask_m[abs(cur_vit_mask / 100)] = mask_amt; - else - mask_p[cur_vit_mask / 100] = mask_amt; - } - cur_vit_mask -= 100; - } - - tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) - | (mask_m[48] << 26) | (mask_m[49] << 24) - | (mask_m[50] << 22) | (mask_m[51] << 20) - | (mask_m[52] << 18) | (mask_m[53] << 16) - | (mask_m[54] << 14) | (mask_m[55] << 12) - | (mask_m[56] << 10) | (mask_m[57] << 8) - | (mask_m[58] << 6) | (mask_m[59] << 4) - | (mask_m[60] << 2) | (mask_m[61] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); - REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); - - tmp_mask = (mask_m[31] << 28) - | (mask_m[32] << 26) | (mask_m[33] << 24) - | (mask_m[34] << 22) | (mask_m[35] << 20) - | (mask_m[36] << 18) | (mask_m[37] << 16) - | (mask_m[48] << 14) | (mask_m[39] << 12) - | (mask_m[40] << 10) | (mask_m[41] << 8) - | (mask_m[42] << 6) | (mask_m[43] << 4) - | (mask_m[44] << 2) | (mask_m[45] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); - - tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) - | (mask_m[18] << 26) | (mask_m[18] << 24) - | (mask_m[20] << 22) | (mask_m[20] << 20) - | (mask_m[22] << 18) | (mask_m[22] << 16) - | (mask_m[24] << 14) | (mask_m[24] << 12) - | (mask_m[25] << 10) | (mask_m[26] << 8) - | (mask_m[27] << 6) | (mask_m[28] << 4) - | (mask_m[29] << 2) | (mask_m[30] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); - - tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) - | (mask_m[2] << 26) | (mask_m[3] << 24) - | (mask_m[4] << 22) | (mask_m[5] << 20) - | (mask_m[6] << 18) | (mask_m[7] << 16) - | (mask_m[8] << 14) | (mask_m[9] << 12) - | (mask_m[10] << 10) | (mask_m[11] << 8) - | (mask_m[12] << 6) | (mask_m[13] << 4) - | (mask_m[14] << 2) | (mask_m[15] << 0); - REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); - - tmp_mask = (mask_p[15] << 28) - | (mask_p[14] << 26) | (mask_p[13] << 24) - | (mask_p[12] << 22) | (mask_p[11] << 20) - | (mask_p[10] << 18) | (mask_p[9] << 16) - | (mask_p[8] << 14) | (mask_p[7] << 12) - | (mask_p[6] << 10) | (mask_p[5] << 8) - | (mask_p[4] << 6) | (mask_p[3] << 4) - | (mask_p[2] << 2) | (mask_p[1] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); - - tmp_mask = (mask_p[30] << 28) - | (mask_p[29] << 26) | (mask_p[28] << 24) - | (mask_p[27] << 22) | (mask_p[26] << 20) - | (mask_p[25] << 18) | (mask_p[24] << 16) - | (mask_p[23] << 14) | (mask_p[22] << 12) - | (mask_p[21] << 10) | (mask_p[20] << 8) - | (mask_p[19] << 6) | (mask_p[18] << 4) - | (mask_p[17] << 2) | (mask_p[16] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); - - tmp_mask = (mask_p[45] << 28) - | (mask_p[44] << 26) | (mask_p[43] << 24) - | (mask_p[42] << 22) | (mask_p[41] << 20) - | (mask_p[40] << 18) | (mask_p[39] << 16) - | (mask_p[38] << 14) | (mask_p[37] << 12) - | (mask_p[36] << 10) | (mask_p[35] << 8) - | (mask_p[34] << 6) | (mask_p[33] << 4) - | (mask_p[32] << 2) | (mask_p[31] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); - - tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) - | (mask_p[59] << 26) | (mask_p[58] << 24) - | (mask_p[57] << 22) | (mask_p[56] << 20) - | (mask_p[55] << 18) | (mask_p[54] << 16) - | (mask_p[53] << 14) | (mask_p[52] << 12) - | (mask_p[51] << 10) | (mask_p[50] << 8) - | (mask_p[49] << 6) | (mask_p[48] << 4) - | (mask_p[47] << 2) | (mask_p[46] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); -} - -/** - * ath9k_hw_rf_alloc_ext_banks - allocates banks for external radio programming - * @ah: atheros hardware structure - * - * Only required for older devices with external AR2133/AR5133 radios. - */ -int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah) -{ -#define ATH_ALLOC_BANK(bank, size) do { \ - bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \ - if (!bank) { \ - ath_print(common, ATH_DBG_FATAL, \ - "Cannot allocate RF banks\n"); \ - return -ENOMEM; \ - } \ - } while (0); - - struct ath_common *common = ath9k_hw_common(ah); - - BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); - - ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows); - ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows); - ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows); - ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows); - ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows); - ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows); - ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows); - ATH_ALLOC_BANK(ah->addac5416_21, - ah->iniAddac.ia_rows * ah->iniAddac.ia_columns); - ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows); - - return 0; -#undef ATH_ALLOC_BANK -} - - -/** - * ath9k_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers - * @ah: atheros hardware struture - * For the external AR2133/AR5133 radios banks. - */ -void -ath9k_hw_rf_free_ext_banks(struct ath_hw *ah) -{ -#define ATH_FREE_BANK(bank) do { \ - kfree(bank); \ - bank = NULL; \ - } while (0); - - BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); - - ATH_FREE_BANK(ah->analogBank0Data); - ATH_FREE_BANK(ah->analogBank1Data); - ATH_FREE_BANK(ah->analogBank2Data); - ATH_FREE_BANK(ah->analogBank3Data); - ATH_FREE_BANK(ah->analogBank6Data); - ATH_FREE_BANK(ah->analogBank6TPCData); - ATH_FREE_BANK(ah->analogBank7Data); - ATH_FREE_BANK(ah->addac5416_21); - ATH_FREE_BANK(ah->bank6Temp); - -#undef ATH_FREE_BANK -} - -/* * - * ath9k_hw_set_rf_regs - programs rf registers based on EEPROM - * @ah: atheros hardware structure - * @chan: - * @modesIndex: - * - * Used for the external AR2133/AR5133 radios. - * - * Reads the EEPROM header info from the device structure and programs - * all rf registers. This routine requires access to the analog - * rf device. This is not required for single-chip devices. - */ -bool ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, - u16 modesIndex) +bool +ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, + u16 modesIndex) { u32 eepMinorRev; u32 ob5GHz = 0, db5GHz = 0; u32 ob2GHz = 0, db2GHz = 0; int regWrites = 0; - /* - * Software does not need to program bank data - * for single chip devices, that is AR9280 or anything - * after that. - */ if (AR_SREV_9280_10_OR_LATER(ah)) return true; - /* Setup rf parameters */ eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); - /* Setup Bank 0 Write */ RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); - /* Setup Bank 1 Write */ RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); - /* Setup Bank 2 Write */ RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); - /* Setup Bank 6 Write */ RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, modesIndex); { @@ -1026,7 +239,6 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, } } - /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ if (eepMinorRev >= 2) { if (IS_CHAN_2GHZ(chan)) { ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2); @@ -1045,10 +257,8 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, } } - /* Setup Bank 7 Setup */ RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); - /* Write Analog registers */ REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, regWrites); REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data, @@ -1064,3 +274,139 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, return true; } + +void +ath9k_hw_rf_free(struct ath_hw *ah) +{ +#define ATH_FREE_BANK(bank) do { \ + kfree(bank); \ + bank = NULL; \ + } while (0); + + ATH_FREE_BANK(ah->analogBank0Data); + ATH_FREE_BANK(ah->analogBank1Data); + ATH_FREE_BANK(ah->analogBank2Data); + ATH_FREE_BANK(ah->analogBank3Data); + ATH_FREE_BANK(ah->analogBank6Data); + ATH_FREE_BANK(ah->analogBank6TPCData); + ATH_FREE_BANK(ah->analogBank7Data); + ATH_FREE_BANK(ah->addac5416_21); + ATH_FREE_BANK(ah->bank6Temp); +#undef ATH_FREE_BANK +} + +bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) +{ + struct ath_common *common = ath9k_hw_common(ah); + + if (!AR_SREV_9280_10_OR_LATER(ah)) { + ah->analogBank0Data = + kzalloc((sizeof(u32) * + ah->iniBank0.ia_rows), GFP_KERNEL); + ah->analogBank1Data = + kzalloc((sizeof(u32) * + ah->iniBank1.ia_rows), GFP_KERNEL); + ah->analogBank2Data = + kzalloc((sizeof(u32) * + ah->iniBank2.ia_rows), GFP_KERNEL); + ah->analogBank3Data = + kzalloc((sizeof(u32) * + ah->iniBank3.ia_rows), GFP_KERNEL); + ah->analogBank6Data = + kzalloc((sizeof(u32) * + ah->iniBank6.ia_rows), GFP_KERNEL); + ah->analogBank6TPCData = + kzalloc((sizeof(u32) * + ah->iniBank6TPC.ia_rows), GFP_KERNEL); + ah->analogBank7Data = + kzalloc((sizeof(u32) * + ah->iniBank7.ia_rows), GFP_KERNEL); + + if (ah->analogBank0Data == NULL + || ah->analogBank1Data == NULL + || ah->analogBank2Data == NULL + || ah->analogBank3Data == NULL + || ah->analogBank6Data == NULL + || ah->analogBank6TPCData == NULL + || ah->analogBank7Data == NULL) { + ath_print(common, ATH_DBG_FATAL, + "Cannot allocate RF banks\n"); + *status = -ENOMEM; + return false; + } + + ah->addac5416_21 = + kzalloc((sizeof(u32) * + ah->iniAddac.ia_rows * + ah->iniAddac.ia_columns), GFP_KERNEL); + if (ah->addac5416_21 == NULL) { + ath_print(common, ATH_DBG_FATAL, + "Cannot allocate addac5416_21\n"); + *status = -ENOMEM; + return false; + } + + ah->bank6Temp = + kzalloc((sizeof(u32) * + ah->iniBank6.ia_rows), GFP_KERNEL); + if (ah->bank6Temp == NULL) { + ath_print(common, ATH_DBG_FATAL, + "Cannot allocate bank6Temp\n"); + *status = -ENOMEM; + return false; + } + } + + return true; +} + +void +ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan) +{ + int i, regWrites = 0; + u32 bank6SelMask; + u32 *bank6Temp = ah->bank6Temp; + + switch (ah->config.diversity_control) { + case ATH9K_ANT_FIXED_A: + bank6SelMask = + (ah->config.antenna_switch_swap & ANTSWAP_AB) ? + REDUCE_CHAIN_0 : REDUCE_CHAIN_1; + break; + case ATH9K_ANT_FIXED_B: + bank6SelMask = + (ah->config.antenna_switch_swap & ANTSWAP_AB) ? + REDUCE_CHAIN_1 : REDUCE_CHAIN_0; + break; + case ATH9K_ANT_VARIABLE: + return; + break; + default: + return; + break; + } + + for (i = 0; i < ah->iniBank6.ia_rows; i++) + bank6Temp[i] = ah->analogBank6Data[i]; + + REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask); + + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0); + + REG_WRITE_RF_ARRAY(&ah->iniBank6, bank6Temp, regWrites); + + REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053); +#ifdef ALTER_SWITCH + REG_WRITE(ah, PHY_SWITCH_CHAIN_0, + (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38) + | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38)); +#endif +} diff --git a/trunk/drivers/net/wireless/ath/ath9k/phy.h b/trunk/drivers/net/wireless/ath/ath9k/phy.h index dc145a135dc7..140fef74c666 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/phy.h +++ b/trunk/drivers/net/wireless/ath/ath9k/phy.h @@ -17,26 +17,20 @@ #ifndef PHY_H #define PHY_H -/* Common between single chip and non single-chip solutions */ -void ath9k_hw_write_regs(struct ath_hw *ah, u32 freqIndex, int regWrites); - -/* Single chip radio settings */ -int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan); -void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); - -/* Routines below are for non single-chip solutions */ -int ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan); -void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); - -int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah); -void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah); - +void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, + struct ath9k_channel + *chan); +bool ath9k_hw_set_channel(struct ath_hw *ah, + struct ath9k_channel *chan); +void ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, + u32 freqIndex, int regWrites); bool ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, u16 modesIndex); - void ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan); +bool ath9k_hw_init_rf(struct ath_hw *ah, + int *status); #define AR_PHY_BASE 0x9800 #define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) @@ -192,20 +186,8 @@ void ath9k_hw_decrease_chain_power(struct ath_hw *ah, #define AR_PHY_PLL_CTL_44_2133 0xeb #define AR_PHY_PLL_CTL_40_2133 0xea -#define AR_PHY_SPECTRAL_SCAN 0x9910 /* AR9280 spectral scan configuration register */ -#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1 -#define AR_PHY_SPECTRAL_SCAN_ENA 0x00000001 /* Enable spectral scan, reg 68, bit 0 */ -#define AR_PHY_SPECTRAL_SCAN_ENA_S 0 /* Enable spectral scan, reg 68, bit 0 */ -#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 /* Activate spectral scan reg 68, bit 1*/ -#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 /* Activate spectral scan reg 68, bit 1*/ -#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 /* Interval for FFT reports, reg 68, bits 4-7*/ -#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4 -#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 /* Interval for FFT reports, reg 68, bits 8-15*/ -#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8 -#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 /* Number of reports, reg 68, bits 16-23*/ -#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16 -#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 /* Short repeat, reg 68, bit 24*/ -#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 /* Short repeat, reg 68, bit 24*/ +#define AR_PHY_SPECTRAL_SCAN 0x9912 +#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1 #define AR_PHY_RX_DELAY 0x9914 #define AR_PHY_SEARCH_START_DELAY 0x9918 diff --git a/trunk/drivers/net/wireless/ath/ath9k/rc.c b/trunk/drivers/net/wireless/ath/ath9k/rc.c index bb72b46567f9..063936423d86 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/rc.c +++ b/trunk/drivers/net/wireless/ath/ath9k/rc.c @@ -679,7 +679,7 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc, return rate; if (rate_table->info[rate].valid_single_stream && - !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) + !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)); return rate; /* This should not happen */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c index 355dd1834e1d..c880a55939bf 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/recv.c +++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c @@ -202,8 +202,7 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, } rcu_read_lock(); - /* XXX: use ieee80211_find_sta! */ - sta = ieee80211_find_sta_by_hw(sc->hw, hdr->addr2); + sta = ieee80211_find_sta(sc->hw, hdr->addr2); if (sta) { an = (struct ath_node *) sta->drv_priv; if (ds->ds_rxstat.rs_rssi != ATH9K_RSSI_BAD && diff --git a/trunk/drivers/net/wireless/ath/ath9k/reg.h b/trunk/drivers/net/wireless/ath/ath9k/reg.h index 061e12ce0b24..ceed0095efac 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/reg.h +++ b/trunk/drivers/net/wireless/ath/ath9k/reg.h @@ -1704,7 +1704,4 @@ enum { #define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24) #define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28) -#define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */ -#define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */ - #endif diff --git a/trunk/drivers/net/wireless/ath/ath9k/xmit.c b/trunk/drivers/net/wireless/ath/ath9k/xmit.c index 8e052f406c35..2a4efcbced60 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/xmit.c +++ b/trunk/drivers/net/wireless/ath/ath9k/xmit.c @@ -282,8 +282,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, rcu_read_lock(); - /* XXX: use ieee80211_find_sta! */ - sta = ieee80211_find_sta_by_hw(sc->hw, hdr->addr1); + sta = ieee80211_find_sta(sc->hw, hdr->addr1); if (!sta) { rcu_read_unlock(); return; diff --git a/trunk/drivers/net/wireless/b43/Kconfig b/trunk/drivers/net/wireless/b43/Kconfig index 64c12e1bced3..54ea61c15d8b 100644 --- a/trunk/drivers/net/wireless/b43/Kconfig +++ b/trunk/drivers/net/wireless/b43/Kconfig @@ -1,6 +1,6 @@ config B43 tristate "Broadcom 43xx wireless support (mac80211 stack)" - depends on SSB_POSSIBLE && MAC80211 && HAS_DMA + depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA select SSB select FW_LOADER ---help--- diff --git a/trunk/drivers/net/wireless/b43/b43.h b/trunk/drivers/net/wireless/b43/b43.h index fe3bf9491997..65b23f725a04 100644 --- a/trunk/drivers/net/wireless/b43/b43.h +++ b/trunk/drivers/net/wireless/b43/b43.h @@ -26,6 +26,8 @@ # define B43_DEBUG 0 #endif +#define B43_RX_MAX_SSI 60 + /* MMIO offsets */ #define B43_MMIO_DMA0_REASON 0x20 #define B43_MMIO_DMA0_IRQ_MASK 0x24 diff --git a/trunk/drivers/net/wireless/b43/dma.c b/trunk/drivers/net/wireless/b43/dma.c index de4e804bedf0..8701034569fa 100644 --- a/trunk/drivers/net/wireless/b43/dma.c +++ b/trunk/drivers/net/wireless/b43/dma.c @@ -1157,9 +1157,8 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot) } static int dma_tx_fragment(struct b43_dmaring *ring, - struct sk_buff **in_skb) + struct sk_buff *skb) { - struct sk_buff *skb = *in_skb; const struct b43_dma_ops *ops = ring->ops; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); u8 *header; @@ -1225,14 +1224,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring, } memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len); - memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb)); - bounce_skb->dev = skb->dev; - skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb)); - info = IEEE80211_SKB_CB(bounce_skb); - dev_kfree_skb_any(skb); skb = bounce_skb; - *in_skb = bounce_skb; meta->skb = skb; meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { @@ -1362,11 +1355,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) * static, so we don't need to store it per frame. */ ring->queue_prio = skb_get_queue_mapping(skb); - /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing - * into the skb data or cb now. */ - hdr = NULL; - info = NULL; - err = dma_tx_fragment(ring, &skb); + err = dma_tx_fragment(ring, skb); if (unlikely(err == -ENOKEY)) { /* Drop this packet, as we don't have the encryption key * anymore and must not transmit it unencrypted. */ diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index 077480c4916a..ed6e96a34743 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -3573,7 +3573,7 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) if (conf->channel->hw_value != phy->channel) b43_switch_channel(dev, conf->channel->hw_value); - dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR); + dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP); /* Adjust the desired TX power level. */ if (conf->power_level != 0) { @@ -4521,8 +4521,9 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, { struct b43_wl *wl = hw_to_b43_wl(hw); - /* FIXME: add locking */ + mutex_lock(&wl->mutex); b43_update_templates(wl); + mutex_unlock(&wl->mutex); return 0; } diff --git a/trunk/drivers/net/wireless/b43/phy_lp.c b/trunk/drivers/net/wireless/b43/phy_lp.c index 3e046ec1ff86..c6987b147af4 100644 --- a/trunk/drivers/net/wireless/b43/phy_lp.c +++ b/trunk/drivers/net/wireless/b43/phy_lp.c @@ -67,7 +67,6 @@ static void b43_lpphy_op_prepare_structs(struct b43_wldev *dev) struct b43_phy_lp *lpphy = phy->lp; memset(lpphy, 0, sizeof(*lpphy)); - lpphy->antenna = B43_ANTENNA_DEFAULT; //TODO } @@ -380,6 +379,8 @@ static void lpphy_save_dig_flt_state(struct b43_wldev *dev) } } +/* lpphy_restore_dig_flt_state is unused but kept as a reference */ +#if 0 static void lpphy_restore_dig_flt_state(struct b43_wldev *dev) { static const u16 addr[] = { @@ -400,6 +401,7 @@ static void lpphy_restore_dig_flt_state(struct b43_wldev *dev) for (i = 0; i < ARRAY_SIZE(addr); i++) b43_phy_write(dev, addr[i], lpphy->dig_flt_state[i]); } +#endif static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) { @@ -752,17 +754,11 @@ static void lpphy_clear_deaf(struct b43_wldev *dev, bool user) } } -static void lpphy_set_trsw_over(struct b43_wldev *dev, bool tx, bool rx) -{ - u16 trsw = (tx << 1) | rx; - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, trsw); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3); -} - static void lpphy_disable_crs(struct b43_wldev *dev, bool user) { lpphy_set_deaf(dev, user); - lpphy_set_trsw_over(dev, false, true); + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1); + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3); b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB); b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4); b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFF7); @@ -797,60 +793,6 @@ static void lpphy_restore_crs(struct b43_wldev *dev, bool user) struct lpphy_tx_gains { u16 gm, pga, pad, dac; }; -static void lpphy_disable_rx_gain_override(struct b43_wldev *dev) -{ - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF); - if (dev->phy.rev >= 2) { - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF); - b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7); - } - } else { - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF); - } -} - -static void lpphy_enable_rx_gain_override(struct b43_wldev *dev) -{ - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40); - if (dev->phy.rev >= 2) { - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400); - b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8); - } - } else { - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200); - } -} - -static void lpphy_disable_tx_gain_override(struct b43_wldev *dev) -{ - if (dev->phy.rev < 2) - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF); - else { - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF); - } - b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF); -} - -static void lpphy_enable_tx_gain_override(struct b43_wldev *dev) -{ - if (dev->phy.rev < 2) - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100); - else { - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x80); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x4000); - } - b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x40); -} - static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev) { struct lpphy_tx_gains gains; @@ -880,17 +822,6 @@ static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac) b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl); } -static u16 lpphy_get_pa_gain(struct b43_wldev *dev) -{ - return b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F; -} - -static void lpphy_set_pa_gain(struct b43_wldev *dev, u16 gain) -{ - b43_phy_maskset(dev, B43_PHY_OFDM(0xFB), 0xE03F, gain << 6); - b43_phy_maskset(dev, B43_PHY_OFDM(0xFD), 0x80FF, gain << 8); -} - static void lpphy_set_tx_gains(struct b43_wldev *dev, struct lpphy_tx_gains gains) { @@ -901,22 +832,25 @@ static void lpphy_set_tx_gains(struct b43_wldev *dev, b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xF800, rf_gain); } else { - pa_gain = lpphy_get_pa_gain(dev); + pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x1FC0; + pa_gain <<= 2; b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, (gains.pga << 8) | gains.gm); - /* - * SPEC FIXME The spec calls for (pa_gain << 8) here, but that - * conflicts with the spec for set_pa_gain! Vendor driver bug? - */ b43_phy_maskset(dev, B43_PHY_OFDM(0xFB), - 0x8000, gains.pad | (pa_gain << 6)); + 0x8000, gains.pad | pa_gain); b43_phy_write(dev, B43_PHY_OFDM(0xFC), (gains.pga << 8) | gains.gm); b43_phy_maskset(dev, B43_PHY_OFDM(0xFD), - 0x8000, gains.pad | (pa_gain << 8)); + 0x8000, gains.pad | pa_gain); } lpphy_set_dac_gain(dev, gains.dac); - lpphy_enable_tx_gain_override(dev); + if (dev->phy.rev < 2) { + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1 << 8); + } else { + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7); + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14); + } + b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF, 1 << 6); } static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain) @@ -956,6 +890,41 @@ static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain) } } +/* lpphy_disable_rx_gain_override is unused but kept as a reference */ +#if 0 +static void lpphy_disable_rx_gain_override(struct b43_wldev *dev) +{ + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE); + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF); + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF); + if (dev->phy.rev >= 2) { + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF); + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF); + b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7); + } + } else { + b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF); + } +} +#endif + +static void lpphy_enable_rx_gain_override(struct b43_wldev *dev) +{ + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1); + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10); + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40); + if (dev->phy.rev >= 2) { + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100); + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400); + b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8); + } + } else { + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200); + } +} + static void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain) { if (dev->phy.rev < 2) @@ -1040,7 +1009,8 @@ static int lpphy_loopback(struct b43_wldev *dev) memset(&iq_est, 0, sizeof(iq_est)); - lpphy_set_trsw_over(dev, true, true); + b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x3); + b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3); b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 1); b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE); b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800); @@ -1162,7 +1132,7 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev, b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0x8FFF, ((u16)lpphy->tssi_npt << 16)); //TODO Set "TSSI Transmit Count" variable to total transmitted frame count - lpphy_disable_tx_gain_override(dev); + //TODO Disable TX gain override lpphy->tx_pwr_idx_over = -1; } } @@ -1348,73 +1318,15 @@ static void lpphy_calibrate_rc(struct b43_wldev *dev) } } -static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) -{ - if (dev->phy.rev >= 2) - return; // rev2+ doesn't support antenna diversity - - if (B43_WARN_ON(antenna > B43_ANTENNA_AUTO1)) - return; - - b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP); - - b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFD, antenna & 0x2); - b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFE, antenna & 0x1); - - b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP); - - dev->phy.lp->antenna = antenna; -} - -static void lpphy_set_tx_iqcc(struct b43_wldev *dev, u16 a, u16 b) -{ - u16 tmp[2]; - - tmp[0] = a; - tmp[1] = b; - b43_lptab_write_bulk(dev, B43_LPTAB16(0, 80), 2, tmp); -} - static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index) { struct b43_phy_lp *lpphy = dev->phy.lp; - struct lpphy_tx_gains gains; - u32 iq_comp, tx_gain, coeff, rf_power; lpphy->tx_pwr_idx_over = index; - lpphy_read_tx_pctl_mode_from_hardware(dev); if (lpphy->txpctl_mode != B43_LPPHY_TXPCTL_OFF) lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_SW); - if (dev->phy.rev >= 2) { - iq_comp = b43_lptab_read(dev, B43_LPTAB32(7, index + 320)); - tx_gain = b43_lptab_read(dev, B43_LPTAB32(7, index + 192)); - gains.pad = (tx_gain >> 16) & 0xFF; - gains.gm = tx_gain & 0xFF; - gains.pga = (tx_gain >> 8) & 0xFF; - gains.dac = (iq_comp >> 28) & 0xFF; - lpphy_set_tx_gains(dev, gains); - } else { - iq_comp = b43_lptab_read(dev, B43_LPTAB32(10, index + 320)); - tx_gain = b43_lptab_read(dev, B43_LPTAB32(10, index + 192)); - b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, - 0xF800, (tx_gain >> 4) & 0x7FFF); - lpphy_set_dac_gain(dev, tx_gain & 0x7); - lpphy_set_pa_gain(dev, (tx_gain >> 24) & 0x7F); - } - lpphy_set_bb_mult(dev, (iq_comp >> 20) & 0xFF); - lpphy_set_tx_iqcc(dev, (iq_comp >> 10) & 0x3FF, iq_comp & 0x3FF); - if (dev->phy.rev >= 2) { - coeff = b43_lptab_read(dev, B43_LPTAB32(7, index + 448)); - } else { - coeff = b43_lptab_read(dev, B43_LPTAB32(10, index + 448)); - } - b43_lptab_write(dev, B43_LPTAB16(0, 85), coeff & 0xFFFF); - if (dev->phy.rev >= 2) { - rf_power = b43_lptab_read(dev, B43_LPTAB32(7, index + 576)); - b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00, - rf_power & 0xFFFF);//SPEC FIXME mask & set != 0 - } - lpphy_enable_tx_gain_override(dev); + + //TODO } static void lpphy_btcoex_override(struct b43_wldev *dev) @@ -1423,45 +1335,58 @@ static void lpphy_btcoex_override(struct b43_wldev *dev) b43_write16(dev, B43_MMIO_BTCOEX_TXCTL, 0xFF); } -static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev, - bool blocked) +static void lpphy_pr41573_workaround(struct b43_wldev *dev) { - //TODO check MAC control register - if (blocked) { - if (dev->phy.rev >= 2) { - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x83FF); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00); - b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0x80FF); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xDFFF); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0808); - } else { - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xE0FF); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFCFF); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0018); - } + struct b43_phy_lp *lpphy = dev->phy.lp; + u32 *saved_tab; + const unsigned int saved_tab_size = 256; + enum b43_lpphy_txpctl_mode txpctl_mode; + s8 tx_pwr_idx_over; + u16 tssi_npt, tssi_idx; + + saved_tab = kcalloc(saved_tab_size, sizeof(saved_tab[0]), GFP_KERNEL); + if (!saved_tab) { + b43err(dev->wl, "PR41573 failed. Out of memory!\n"); + return; + } + + lpphy_read_tx_pctl_mode_from_hardware(dev); + txpctl_mode = lpphy->txpctl_mode; + tx_pwr_idx_over = lpphy->tx_pwr_idx_over; + tssi_npt = lpphy->tssi_npt; + tssi_idx = lpphy->tssi_idx; + + if (dev->phy.rev < 2) { + b43_lptab_read_bulk(dev, B43_LPTAB32(10, 0x140), + saved_tab_size, saved_tab); } else { - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xE0FF); - if (dev->phy.rev >= 2) - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xF7F7); - else - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFE7); + b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140), + saved_tab_size, saved_tab); } + //TODO + + kfree(saved_tab); } -/* This was previously called lpphy_japan_filter */ -static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel) +static void lpphy_calibration(struct b43_wldev *dev) { struct b43_phy_lp *lpphy = dev->phy.lp; - u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter! + enum b43_lpphy_txpctl_mode saved_pctl_mode; - if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific? - b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9); - if ((dev->phy.rev == 1) && (lpphy->rc_cap)) - lpphy_set_rc_cap(dev); - } else { - b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F); - } + b43_mac_suspend(dev); + + lpphy_btcoex_override(dev); + lpphy_read_tx_pctl_mode_from_hardware(dev); + saved_pctl_mode = lpphy->txpctl_mode; + lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); + //TODO Perform transmit power table I/Q LO calibration + if ((dev->phy.rev == 0) && (saved_pctl_mode != B43_LPPHY_TXPCTL_OFF)) + lpphy_pr41573_workaround(dev); + //TODO If a full calibration has not been performed on this channel yet, perform PAPD TX-power calibration + lpphy_set_tx_power_control(dev, saved_pctl_mode); + //TODO Perform I/Q calibration with a single control value set + + b43_mac_enable(dev); } static void lpphy_set_tssi_mux(struct b43_wldev *dev, enum tssi_mux_mode mode) @@ -1570,473 +1495,6 @@ static void lpphy_tx_pctl_init(struct b43_wldev *dev) } } -static void lpphy_pr41573_workaround(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - u32 *saved_tab; - const unsigned int saved_tab_size = 256; - enum b43_lpphy_txpctl_mode txpctl_mode; - s8 tx_pwr_idx_over; - u16 tssi_npt, tssi_idx; - - saved_tab = kcalloc(saved_tab_size, sizeof(saved_tab[0]), GFP_KERNEL); - if (!saved_tab) { - b43err(dev->wl, "PR41573 failed. Out of memory!\n"); - return; - } - - lpphy_read_tx_pctl_mode_from_hardware(dev); - txpctl_mode = lpphy->txpctl_mode; - tx_pwr_idx_over = lpphy->tx_pwr_idx_over; - tssi_npt = lpphy->tssi_npt; - tssi_idx = lpphy->tssi_idx; - - if (dev->phy.rev < 2) { - b43_lptab_read_bulk(dev, B43_LPTAB32(10, 0x140), - saved_tab_size, saved_tab); - } else { - b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140), - saved_tab_size, saved_tab); - } - //FIXME PHY reset - lpphy_table_init(dev); //FIXME is table init needed? - lpphy_baseband_init(dev); - lpphy_tx_pctl_init(dev); - b43_lpphy_op_software_rfkill(dev, false); - lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); - if (dev->phy.rev < 2) { - b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0x140), - saved_tab_size, saved_tab); - } else { - b43_lptab_write_bulk(dev, B43_LPTAB32(7, 0x140), - saved_tab_size, saved_tab); - } - b43_write16(dev, B43_MMIO_CHANNEL, lpphy->channel); - lpphy->tssi_npt = tssi_npt; - lpphy->tssi_idx = tssi_idx; - lpphy_set_analog_filter(dev, lpphy->channel); - if (tx_pwr_idx_over != -1) - lpphy_set_tx_power_by_index(dev, tx_pwr_idx_over); - if (lpphy->rc_cap) - lpphy_set_rc_cap(dev); - b43_lpphy_op_set_rx_antenna(dev, lpphy->antenna); - lpphy_set_tx_power_control(dev, txpctl_mode); - kfree(saved_tab); -} - -struct lpphy_rx_iq_comp { u8 chan; s8 c1, c0; }; - -static const struct lpphy_rx_iq_comp lpphy_5354_iq_table[] = { - { .chan = 1, .c1 = -66, .c0 = 15, }, - { .chan = 2, .c1 = -66, .c0 = 15, }, - { .chan = 3, .c1 = -66, .c0 = 15, }, - { .chan = 4, .c1 = -66, .c0 = 15, }, - { .chan = 5, .c1 = -66, .c0 = 15, }, - { .chan = 6, .c1 = -66, .c0 = 15, }, - { .chan = 7, .c1 = -66, .c0 = 14, }, - { .chan = 8, .c1 = -66, .c0 = 14, }, - { .chan = 9, .c1 = -66, .c0 = 14, }, - { .chan = 10, .c1 = -66, .c0 = 14, }, - { .chan = 11, .c1 = -66, .c0 = 14, }, - { .chan = 12, .c1 = -66, .c0 = 13, }, - { .chan = 13, .c1 = -66, .c0 = 13, }, - { .chan = 14, .c1 = -66, .c0 = 13, }, -}; - -static const struct lpphy_rx_iq_comp lpphy_rev0_1_iq_table[] = { - { .chan = 1, .c1 = -64, .c0 = 13, }, - { .chan = 2, .c1 = -64, .c0 = 13, }, - { .chan = 3, .c1 = -64, .c0 = 13, }, - { .chan = 4, .c1 = -64, .c0 = 13, }, - { .chan = 5, .c1 = -64, .c0 = 12, }, - { .chan = 6, .c1 = -64, .c0 = 12, }, - { .chan = 7, .c1 = -64, .c0 = 12, }, - { .chan = 8, .c1 = -64, .c0 = 12, }, - { .chan = 9, .c1 = -64, .c0 = 12, }, - { .chan = 10, .c1 = -64, .c0 = 11, }, - { .chan = 11, .c1 = -64, .c0 = 11, }, - { .chan = 12, .c1 = -64, .c0 = 11, }, - { .chan = 13, .c1 = -64, .c0 = 11, }, - { .chan = 14, .c1 = -64, .c0 = 10, }, - { .chan = 34, .c1 = -62, .c0 = 24, }, - { .chan = 38, .c1 = -62, .c0 = 24, }, - { .chan = 42, .c1 = -62, .c0 = 24, }, - { .chan = 46, .c1 = -62, .c0 = 23, }, - { .chan = 36, .c1 = -62, .c0 = 24, }, - { .chan = 40, .c1 = -62, .c0 = 24, }, - { .chan = 44, .c1 = -62, .c0 = 23, }, - { .chan = 48, .c1 = -62, .c0 = 23, }, - { .chan = 52, .c1 = -62, .c0 = 23, }, - { .chan = 56, .c1 = -62, .c0 = 22, }, - { .chan = 60, .c1 = -62, .c0 = 22, }, - { .chan = 64, .c1 = -62, .c0 = 22, }, - { .chan = 100, .c1 = -62, .c0 = 16, }, - { .chan = 104, .c1 = -62, .c0 = 16, }, - { .chan = 108, .c1 = -62, .c0 = 15, }, - { .chan = 112, .c1 = -62, .c0 = 14, }, - { .chan = 116, .c1 = -62, .c0 = 14, }, - { .chan = 120, .c1 = -62, .c0 = 13, }, - { .chan = 124, .c1 = -62, .c0 = 12, }, - { .chan = 128, .c1 = -62, .c0 = 12, }, - { .chan = 132, .c1 = -62, .c0 = 12, }, - { .chan = 136, .c1 = -62, .c0 = 11, }, - { .chan = 140, .c1 = -62, .c0 = 10, }, - { .chan = 149, .c1 = -61, .c0 = 9, }, - { .chan = 153, .c1 = -61, .c0 = 9, }, - { .chan = 157, .c1 = -61, .c0 = 9, }, - { .chan = 161, .c1 = -61, .c0 = 8, }, - { .chan = 165, .c1 = -61, .c0 = 8, }, - { .chan = 184, .c1 = -62, .c0 = 25, }, - { .chan = 188, .c1 = -62, .c0 = 25, }, - { .chan = 192, .c1 = -62, .c0 = 25, }, - { .chan = 196, .c1 = -62, .c0 = 25, }, - { .chan = 200, .c1 = -62, .c0 = 25, }, - { .chan = 204, .c1 = -62, .c0 = 25, }, - { .chan = 208, .c1 = -62, .c0 = 25, }, - { .chan = 212, .c1 = -62, .c0 = 25, }, - { .chan = 216, .c1 = -62, .c0 = 26, }, -}; - -static const struct lpphy_rx_iq_comp lpphy_rev2plus_iq_comp = { - .chan = 0, - .c1 = -64, - .c0 = 0, -}; - -static u8 lpphy_nbits(s32 val) -{ - u32 tmp = abs(val); - u8 nbits = 0; - - while (tmp != 0) { - nbits++; - tmp >>= 1; - } - - return nbits; -} - -static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples) -{ - struct lpphy_iq_est iq_est; - u16 c0, c1; - int prod, ipwr, qpwr, prod_msb, q_msb, tmp1, tmp2, tmp3, tmp4, ret; - - c1 = b43_phy_read(dev, B43_LPPHY_RX_COMP_COEFF_S); - c0 = c1 >> 8; - c1 |= 0xFF; - - b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, 0x00C0); - b43_phy_mask(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF); - - ret = lpphy_rx_iq_est(dev, samples, 32, &iq_est); - if (!ret) - goto out; - - prod = iq_est.iq_prod; - ipwr = iq_est.i_pwr; - qpwr = iq_est.q_pwr; - - if (ipwr + qpwr < 2) { - ret = 0; - goto out; - } - - prod_msb = lpphy_nbits(prod); - q_msb = lpphy_nbits(qpwr); - tmp1 = prod_msb - 20; - - if (tmp1 >= 0) { - tmp3 = ((prod << (30 - prod_msb)) + (ipwr >> (1 + tmp1))) / - (ipwr >> tmp1); - } else { - tmp3 = ((prod << (30 - prod_msb)) + (ipwr << (-1 - tmp1))) / - (ipwr << -tmp1); - } - - tmp2 = q_msb - 11; - - if (tmp2 >= 0) - tmp4 = (qpwr << (31 - q_msb)) / (ipwr >> tmp2); - else - tmp4 = (qpwr << (31 - q_msb)) / (ipwr << -tmp2); - - tmp4 -= tmp3 * tmp3; - tmp4 = -int_sqrt(tmp4); - - c0 = tmp3 >> 3; - c1 = tmp4 >> 4; - -out: - b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, c1); - b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF, c0 << 8); - return ret; -} - -/* Complex number using 2 32-bit signed integers */ -typedef struct {s32 i, q;} lpphy_c32; - -static lpphy_c32 lpphy_cordic(int theta) -{ - u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304, - 58666, 29335, 14668, 7334, 3667, 1833, 917, 458, - 229, 115, 57, 29, }; - int i, tmp, signx = 1, angle = 0; - lpphy_c32 ret = { .i = 39797, .q = 0, }; - - theta = clamp_t(int, theta, -180, 180); - - if (theta > 90) { - theta -= 180; - signx = -1; - } else if (theta < -90) { - theta += 180; - signx = -1; - } - - for (i = 0; i <= 17; i++) { - if (theta > angle) { - tmp = ret.i - (ret.q >> i); - ret.q += ret.i >> i; - ret.i = tmp; - angle += arctg[i]; - } else { - tmp = ret.i + (ret.q >> i); - ret.q -= ret.i >> i; - ret.i = tmp; - angle -= arctg[i]; - } - } - - ret.i *= signx; - ret.q *= signx; - - return ret; -} - -static void lpphy_run_samples(struct b43_wldev *dev, u16 samples, u16 loops, - u16 wait) -{ - b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL, - 0xFFC0, samples - 1); - if (loops != 0xFFFF) - loops--; - b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000, loops); - b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL, 0x3F, wait << 6); - b43_phy_set(dev, B43_LPPHY_A_PHY_CTL_ADDR, 0x1); -} - -//SPEC FIXME what does a negative freq mean? -static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - u16 buf[64]; - int i, samples = 0, angle = 0, rotation = (9 * freq) / 500; - lpphy_c32 sample; - - lpphy->tx_tone_freq = freq; - - if (freq) { - /* Find i for which abs(freq) integrally divides 20000 * i */ - for (i = 1; samples * abs(freq) != 20000 * i; i++) { - samples = (20000 * i) / abs(freq); - if(B43_WARN_ON(samples > 63)) - return; - } - } else { - samples = 2; - } - - for (i = 0; i < samples; i++) { - sample = lpphy_cordic(angle); - angle += rotation; - buf[i] = ((sample.i * max) & 0xFF) << 8; - buf[i] |= (sample.q * max) & 0xFF; - } - - b43_lptab_write_bulk(dev, B43_LPTAB16(5, 0), samples, buf); - - lpphy_run_samples(dev, samples, 0xFFFF, 0); -} - -static void lpphy_stop_tx_tone(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - int i; - - lpphy->tx_tone_freq = 0; - - b43_phy_mask(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000); - for (i = 0; i < 31; i++) { - if (!(b43_phy_read(dev, B43_LPPHY_A_PHY_CTL_ADDR) & 0x1)) - break; - udelay(100); - } -} - - -static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains, - int mode, bool useindex, u8 index) -{ - //TODO -} - -static void lpphy_papd_cal_txpwr(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; - struct lpphy_tx_gains gains, oldgains; - int old_txpctl, old_afe_ovr, old_rf, old_bbmult; - - lpphy_read_tx_pctl_mode_from_hardware(dev); - old_txpctl = lpphy->txpctl_mode; - old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40; - if (old_afe_ovr) - oldgains = lpphy_get_tx_gains(dev); - old_rf = b43_phy_read(dev, B43_LPPHY_RF_PWR_OVERRIDE) & 0xFF; - old_bbmult = lpphy_get_bb_mult(dev); - - lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); - - if (bus->chip_id == 0x4325 && bus->chip_rev == 0) - lpphy_papd_cal(dev, gains, 0, 1, 30); - else - lpphy_papd_cal(dev, gains, 0, 1, 65); - - if (old_afe_ovr) - lpphy_set_tx_gains(dev, oldgains); - lpphy_set_bb_mult(dev, old_bbmult); - lpphy_set_tx_power_control(dev, old_txpctl); - b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00, old_rf); -} - -static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx, - bool rx, bool pa, struct lpphy_tx_gains *gains) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; - const struct lpphy_rx_iq_comp *iqcomp = NULL; - struct lpphy_tx_gains nogains, oldgains; - u16 tmp; - int i, ret; - - memset(&nogains, 0, sizeof(nogains)); - memset(&oldgains, 0, sizeof(oldgains)); - - if (bus->chip_id == 0x5354) { - for (i = 0; i < ARRAY_SIZE(lpphy_5354_iq_table); i++) { - if (lpphy_5354_iq_table[i].chan == lpphy->channel) { - iqcomp = &lpphy_5354_iq_table[i]; - } - } - } else if (dev->phy.rev >= 2) { - iqcomp = &lpphy_rev2plus_iq_comp; - } else { - for (i = 0; i < ARRAY_SIZE(lpphy_rev0_1_iq_table); i++) { - if (lpphy_rev0_1_iq_table[i].chan == lpphy->channel) { - iqcomp = &lpphy_rev0_1_iq_table[i]; - } - } - } - - if (B43_WARN_ON(!iqcomp)) - return 0; - - b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, iqcomp->c1); - b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, - 0x00FF, iqcomp->c0 << 8); - - if (noise) { - tx = true; - rx = false; - pa = false; - } - - lpphy_set_trsw_over(dev, tx, rx); - - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8); - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, - 0xFFF7, pa << 3); - } else { - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20); - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, - 0xFFDF, pa << 5); - } - - tmp = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40; - - if (noise) - lpphy_set_rx_gain(dev, 0x2D5D); - else { - if (tmp) - oldgains = lpphy_get_tx_gains(dev); - if (!gains) - gains = &nogains; - lpphy_set_tx_gains(dev, *gains); - } - - b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE); - b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800); - lpphy_set_deaf(dev, false); - if (noise) - ret = lpphy_calc_rx_iq_comp(dev, 0xFFF0); - else { - lpphy_start_tx_tone(dev, 4000, 100); - ret = lpphy_calc_rx_iq_comp(dev, 0x4000); - lpphy_stop_tx_tone(dev); - } - lpphy_clear_deaf(dev, false); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFC); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFDF); - if (!noise) { - if (tmp) - lpphy_set_tx_gains(dev, oldgains); - else - lpphy_disable_tx_gain_override(dev); - } - lpphy_disable_rx_gain_override(dev); - b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE); - b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xF7FF); - return ret; -} - -static void lpphy_calibration(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - enum b43_lpphy_txpctl_mode saved_pctl_mode; - bool full_cal = false; - - if (lpphy->full_calib_chan != lpphy->channel) { - full_cal = true; - lpphy->full_calib_chan = lpphy->channel; - } - - b43_mac_suspend(dev); - - lpphy_btcoex_override(dev); - if (dev->phy.rev >= 2) - lpphy_save_dig_flt_state(dev); - lpphy_read_tx_pctl_mode_from_hardware(dev); - saved_pctl_mode = lpphy->txpctl_mode; - lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); - //TODO Perform transmit power table I/Q LO calibration - if ((dev->phy.rev == 0) && (saved_pctl_mode != B43_LPPHY_TXPCTL_OFF)) - lpphy_pr41573_workaround(dev); - if ((dev->phy.rev >= 2) && full_cal) { - lpphy_papd_cal_txpwr(dev); - } - lpphy_set_tx_power_control(dev, saved_pctl_mode); - if (dev->phy.rev >= 2) - lpphy_restore_dig_flt_state(dev); - lpphy_rx_iq_cal(dev, true, true, false, false, NULL); - - b43_mac_enable(dev); -} - static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg) { b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); @@ -2081,6 +1539,12 @@ static void b43_lpphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); } +static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev, + bool blocked) +{ + //TODO +} + struct b206x_channel { u8 channel; u16 freq; @@ -2546,6 +2010,22 @@ static int lpphy_b2062_tune(struct b43_wldev *dev, return err; } + +/* This was previously called lpphy_japan_filter */ +static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel) +{ + struct b43_phy_lp *lpphy = dev->phy.lp; + u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter! + + if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific? + b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9); + if ((dev->phy.rev == 1) && (lpphy->rc_cap)) + lpphy_set_rc_cap(dev); + } else { + b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F); + } +} + static void lpphy_b2063_vco_calib(struct b43_wldev *dev) { u16 tmp; @@ -2730,6 +2210,18 @@ static int b43_lpphy_op_init(struct b43_wldev *dev) return 0; } +static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) +{ + if (dev->phy.rev >= 2) + return; // rev2+ doesn't support antenna diversity + + if (B43_WARN_ON(antenna > B43_ANTENNA_AUTO1)) + return; + + b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFD, antenna & 0x2); + b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFE, antenna & 0x1); +} + static void b43_lpphy_op_adjust_txpower(struct b43_wldev *dev) { //TODO @@ -2752,11 +2244,6 @@ void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on) } } -static void b43_lpphy_op_pwork_15sec(struct b43_wldev *dev) -{ - //TODO -} - const struct b43_phy_operations b43_phyops_lp = { .allocate = b43_lpphy_op_allocate, .free = b43_lpphy_op_free, @@ -2774,6 +2261,4 @@ const struct b43_phy_operations b43_phyops_lp = { .set_rx_antenna = b43_lpphy_op_set_rx_antenna, .recalc_txpower = b43_lpphy_op_recalc_txpower, .adjust_txpower = b43_lpphy_op_adjust_txpower, - .pwork_15sec = b43_lpphy_op_pwork_15sec, - .pwork_60sec = lpphy_calibration, }; diff --git a/trunk/drivers/net/wireless/b43/phy_lp.h b/trunk/drivers/net/wireless/b43/phy_lp.h index 62737f700cbc..c3232c17b60a 100644 --- a/trunk/drivers/net/wireless/b43/phy_lp.h +++ b/trunk/drivers/net/wireless/b43/phy_lp.h @@ -286,7 +286,6 @@ #define B43_LPPHY_TR_LOOKUP_6 B43_PHY_OFDM(0xC8) /* TR Lookup 6 */ #define B43_LPPHY_TR_LOOKUP_7 B43_PHY_OFDM(0xC9) /* TR Lookup 7 */ #define B43_LPPHY_TR_LOOKUP_8 B43_PHY_OFDM(0xCA) /* TR Lookup 8 */ -#define B43_LPPHY_RF_PWR_OVERRIDE B43_PHY_OFDM(0xD3) /* RF power override */ @@ -872,12 +871,12 @@ struct b43_phy_lp { u8 rssi_gs; /* RC cap */ - u8 rc_cap; + u8 rc_cap; /* FIXME initial value? */ /* BX arch */ u8 bx_arch; /* Full calibration channel */ - u8 full_calib_chan; + u8 full_calib_chan; /* FIXME initial value? */ /* Transmit iqlocal best coeffs */ bool tx_iqloc_best_coeffs_valid; @@ -892,12 +891,6 @@ struct b43_phy_lp { /* The channel we are tuned to */ u8 channel; - - /* The active antenna diversity mode */ - int antenna; - - /* Frequency of the active TX tone */ - int tx_tone_freq; }; enum tssi_mux_mode { diff --git a/trunk/drivers/net/wireless/b43/xmit.c b/trunk/drivers/net/wireless/b43/xmit.c index eda06529ef5f..7a5e294be2bc 100644 --- a/trunk/drivers/net/wireless/b43/xmit.c +++ b/trunk/drivers/net/wireless/b43/xmit.c @@ -621,6 +621,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) (phystat0 & B43_RX_PHYST0_OFDM), (phystat0 & B43_RX_PHYST0_GAINCTL), (phystat3 & B43_RX_PHYST3_TRSTATE)); + status.qual = (rxhdr->jssi * 100) / B43_RX_MAX_SSI; } if (phystat0 & B43_RX_PHYST0_OFDM) diff --git a/trunk/drivers/net/wireless/b43legacy/Kconfig b/trunk/drivers/net/wireless/b43legacy/Kconfig index 1ffa28835c58..94a463478053 100644 --- a/trunk/drivers/net/wireless/b43legacy/Kconfig +++ b/trunk/drivers/net/wireless/b43legacy/Kconfig @@ -1,6 +1,6 @@ config B43LEGACY tristate "Broadcom 43xx-legacy wireless support (mac80211 stack)" - depends on SSB_POSSIBLE && MAC80211 && HAS_DMA + depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA select SSB select FW_LOADER ---help--- diff --git a/trunk/drivers/net/wireless/b43legacy/b43legacy.h b/trunk/drivers/net/wireless/b43legacy/b43legacy.h index 89fe2f972c72..038baa8869e2 100644 --- a/trunk/drivers/net/wireless/b43legacy/b43legacy.h +++ b/trunk/drivers/net/wireless/b43legacy/b43legacy.h @@ -29,6 +29,8 @@ #define B43legacy_IRQWAIT_MAX_RETRIES 20 +#define B43legacy_RX_MAX_SSI 60 /* best guess at max ssi */ + /* MMIO offsets */ #define B43legacy_MMIO_DMA0_REASON 0x20 #define B43legacy_MMIO_DMA0_IRQ_MASK 0x24 diff --git a/trunk/drivers/net/wireless/b43legacy/dma.c b/trunk/drivers/net/wireless/b43legacy/dma.c index 0a86bdf53154..866403415811 100644 --- a/trunk/drivers/net/wireless/b43legacy/dma.c +++ b/trunk/drivers/net/wireless/b43legacy/dma.c @@ -1240,9 +1240,8 @@ struct b43legacy_dmaring *parse_cookie(struct b43legacy_wldev *dev, } static int dma_tx_fragment(struct b43legacy_dmaring *ring, - struct sk_buff **in_skb) + struct sk_buff *skb) { - struct sk_buff *skb = *in_skb; const struct b43legacy_dma_ops *ops = ring->ops; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); u8 *header; @@ -1306,14 +1305,8 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, } memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len); - memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb)); - bounce_skb->dev = skb->dev; - skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb)); - info = IEEE80211_SKB_CB(bounce_skb); - dev_kfree_skb_any(skb); skb = bounce_skb; - *in_skb = bounce_skb; meta->skb = skb; meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { @@ -1367,10 +1360,8 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev, struct sk_buff *skb) { struct b43legacy_dmaring *ring; - struct ieee80211_hdr *hdr; int err = 0; unsigned long flags; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ring = priority_to_txring(dev, skb_get_queue_mapping(skb)); spin_lock_irqsave(&ring->lock, flags); @@ -1395,11 +1386,7 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev, goto out_unlock; } - /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing - * into the skb data or cb now. */ - hdr = NULL; - info = NULL; - err = dma_tx_fragment(ring, &skb); + err = dma_tx_fragment(ring, skb); if (unlikely(err == -ENOKEY)) { /* Drop this packet, as we don't have the encryption key * anymore and must not transmit it unencrypted. */ diff --git a/trunk/drivers/net/wireless/b43legacy/main.c b/trunk/drivers/net/wireless/b43legacy/main.c index d579bb9035c4..0983406f4630 100644 --- a/trunk/drivers/net/wireless/b43legacy/main.c +++ b/trunk/drivers/net/wireless/b43legacy/main.c @@ -2676,7 +2676,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, if (conf->channel->hw_value != phy->channel) b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0); - dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR); + dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP); /* Adjust the desired TX power level. */ if (conf->power_level != 0) { diff --git a/trunk/drivers/net/wireless/b43legacy/xmit.c b/trunk/drivers/net/wireless/b43legacy/xmit.c index 9c8882d9275e..103f3c9e7f58 100644 --- a/trunk/drivers/net/wireless/b43legacy/xmit.c +++ b/trunk/drivers/net/wireless/b43legacy/xmit.c @@ -549,6 +549,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev, (phystat0 & B43legacy_RX_PHYST0_GAINCTL), (phystat3 & B43legacy_RX_PHYST3_TRSTATE)); status.noise = dev->stats.link_noise; + status.qual = (jssi * 100) / B43legacy_RX_MAX_SSI; /* change to support A PHY */ if (phystat0 & B43legacy_RX_PHYST0_OFDM) status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false); diff --git a/trunk/drivers/net/wireless/hostap/Kconfig b/trunk/drivers/net/wireless/hostap/Kconfig index 287d82728bc3..08f1e989653d 100644 --- a/trunk/drivers/net/wireless/hostap/Kconfig +++ b/trunk/drivers/net/wireless/hostap/Kconfig @@ -1,5 +1,6 @@ config HOSTAP tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)" + depends on WLAN_80211 select WIRELESS_EXT select WEXT_SPY select WEXT_PRIV diff --git a/trunk/drivers/staging/wavelan/i82586.h b/trunk/drivers/net/wireless/i82586.h similarity index 100% rename from trunk/drivers/staging/wavelan/i82586.h rename to trunk/drivers/net/wireless/i82586.h diff --git a/trunk/drivers/staging/wavelan/i82593.h b/trunk/drivers/net/wireless/i82593.h similarity index 100% rename from trunk/drivers/staging/wavelan/i82593.h rename to trunk/drivers/net/wireless/i82593.h diff --git a/trunk/drivers/net/wireless/ipw2x00/Kconfig b/trunk/drivers/net/wireless/ipw2x00/Kconfig index 2715b101aded..59ec9eec5024 100644 --- a/trunk/drivers/net/wireless/ipw2x00/Kconfig +++ b/trunk/drivers/net/wireless/ipw2x00/Kconfig @@ -4,7 +4,7 @@ config IPW2100 tristate "Intel PRO/Wireless 2100 Network Connection" - depends on PCI && CFG80211 + depends on PCI && WLAN_80211 && CFG80211 select WIRELESS_EXT select WEXT_SPY select WEXT_PRIV @@ -65,7 +65,7 @@ config IPW2100_DEBUG config IPW2200 tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection" - depends on PCI && CFG80211 && CFG80211_WEXT + depends on PCI && WLAN_80211 && CFG80211 && CFG80211_WEXT select WIRELESS_EXT select WEXT_SPY select WEXT_PRIV @@ -154,7 +154,7 @@ config IPW2200_DEBUG config LIBIPW tristate - depends on PCI && CFG80211 + depends on PCI && WLAN_80211 && CFG80211 select WIRELESS_EXT select WEXT_SPY select CRYPTO diff --git a/trunk/drivers/net/wireless/iwlwifi/Kconfig b/trunk/drivers/net/wireless/iwlwifi/Kconfig index b16b06c2031f..c82c97be7bfa 100644 --- a/trunk/drivers/net/wireless/iwlwifi/Kconfig +++ b/trunk/drivers/net/wireless/iwlwifi/Kconfig @@ -1,6 +1,6 @@ config IWLWIFI tristate "Intel Wireless Wifi" - depends on PCI && MAC80211 && EXPERIMENTAL + depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL select FW_LOADER config IWLWIFI_SPECTRUM_MEASUREMENT diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c index 8f82537045bf..3a645e485dda 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -164,13 +164,12 @@ struct iwl_cfg iwl1000_bgn_cfg = { .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, - .set_l0s = true, + .set_l0s = false, .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_1000, .shadow_ram_support = false, .ht_greenfield_support = true, .led_compensation = 51, - .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .support_ct_kill_exit = true, }; @@ -191,7 +190,7 @@ struct iwl_cfg iwl1000_bg_cfg = { .valid_tx_ant = ANT_A, .valid_rx_ant = ANT_AB, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, - .set_l0s = true, + .set_l0s = false, .use_bsm = false, .max_ll_items = OTP_MAX_LL_ITEMS_1000, .shadow_ram_support = false, diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index dc81e19674f7..cbb0585083a9 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -42,6 +42,38 @@ #define RS_NAME "iwl-3945-rs" +struct iwl3945_rate_scale_data { + u64 data; + s32 success_counter; + s32 success_ratio; + s32 counter; + s32 average_tpt; + unsigned long stamp; +}; + +struct iwl3945_rs_sta { + spinlock_t lock; + struct iwl_priv *priv; + s32 *expected_tpt; + unsigned long last_partial_flush; + unsigned long last_flush; + u32 flush_time; + u32 last_tx_packets; + u32 tx_packets; + u8 tgg; + u8 flush_pending; + u8 start_rate; + u8 ibss_sta_added; + struct timer_list rate_scale_flush; + struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945]; +#ifdef CONFIG_MAC80211_DEBUGFS + struct dentry *rs_sta_dbgfs_stats_table_file; +#endif + + /* used to be in sta_info */ + int last_txrate_idx; +}; + static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = { 7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202 }; @@ -338,28 +370,6 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, IWL_DEBUG_RATE(priv, "enter\n"); - spin_lock_init(&rs_sta->lock); - - rs_sta->priv = priv; - - rs_sta->start_rate = IWL_RATE_INVALID; - - /* default to just 802.11b */ - rs_sta->expected_tpt = iwl3945_expected_tpt_b; - - rs_sta->last_partial_flush = jiffies; - rs_sta->last_flush = jiffies; - rs_sta->flush_time = IWL_RATE_FLUSH; - rs_sta->last_tx_packets = 0; - rs_sta->ibss_sta_added = 0; - - init_timer(&rs_sta->rate_scale_flush); - rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; - rs_sta->rate_scale_flush.function = &iwl3945_bg_rate_scale_flush; - - for (i = 0; i < IWL_RATE_COUNT_3945; i++) - iwl3945_clear_window(&rs_sta->win[i]); - /* TODO: what is a good starting rate for STA? About middle? Maybe not * the lowest or the highest rate.. Could consider using RSSI from * previous packets? Need to have IEEE 802.1X auth succeed immediately @@ -399,11 +409,45 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) { struct iwl3945_rs_sta *rs_sta; struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; - struct iwl_priv *priv __maybe_unused = iwl_priv; + struct iwl_priv *priv = iwl_priv; + int i; + + /* + * XXX: If it's using sta->drv_priv anyway, it might + * as well just put all the information there. + */ IWL_DEBUG_RATE(priv, "enter\n"); - rs_sta = &psta->rs_sta; + rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp); + if (!rs_sta) { + IWL_DEBUG_RATE(priv, "leave: ENOMEM\n"); + return NULL; + } + + psta->rs_sta = rs_sta; + + spin_lock_init(&rs_sta->lock); + + rs_sta->priv = priv; + + rs_sta->start_rate = IWL_RATE_INVALID; + + /* default to just 802.11b */ + rs_sta->expected_tpt = iwl3945_expected_tpt_b; + + rs_sta->last_partial_flush = jiffies; + rs_sta->last_flush = jiffies; + rs_sta->flush_time = IWL_RATE_FLUSH; + rs_sta->last_tx_packets = 0; + rs_sta->ibss_sta_added = 0; + + init_timer(&rs_sta->rate_scale_flush); + rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; + rs_sta->rate_scale_flush.function = &iwl3945_bg_rate_scale_flush; + + for (i = 0; i < IWL_RATE_COUNT_3945; i++) + iwl3945_clear_window(&rs_sta->win[i]); IWL_DEBUG_RATE(priv, "leave\n"); @@ -414,11 +458,14 @@ static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, void *priv_sta) { struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; - struct iwl3945_rs_sta *rs_sta = &psta->rs_sta; + struct iwl3945_rs_sta *rs_sta = priv_sta; struct iwl_priv *priv __maybe_unused = rs_sta->priv; + psta->rs_sta = NULL; + IWL_DEBUG_RATE(priv, "enter\n"); del_timer_sync(&rs_sta->rate_scale_flush); + kfree(rs_sta); IWL_DEBUG_RATE(priv, "leave\n"); } @@ -913,15 +960,14 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) rcu_read_lock(); - sta = ieee80211_find_sta(priv->vif, - priv->stations[sta_id].sta.sta.addr); + sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr); if (!sta) { rcu_read_unlock(); return; } psta = (void *) sta->drv_priv; - rs_sta = &psta->rs_sta; + rs_sta = psta->rs_sta; spin_lock_irqsave(&rs_sta->lock, flags); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-3945.h b/trunk/drivers/net/wireless/iwlwifi/iwl-3945.h index 2b0d65c5780a..ebb999a51b58 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -74,41 +74,8 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; /* Module parameters accessible from iwl-*.c */ extern struct iwl_mod_params iwl3945_mod_params; -struct iwl3945_rate_scale_data { - u64 data; - s32 success_counter; - s32 success_ratio; - s32 counter; - s32 average_tpt; - unsigned long stamp; -}; - -struct iwl3945_rs_sta { - spinlock_t lock; - struct iwl_priv *priv; - s32 *expected_tpt; - unsigned long last_partial_flush; - unsigned long last_flush; - u32 flush_time; - u32 last_tx_packets; - u32 tx_packets; - u8 tgg; - u8 flush_pending; - u8 start_rate; - u8 ibss_sta_added; - struct timer_list rate_scale_flush; - struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945]; -#ifdef CONFIG_MAC80211_DEBUGFS - struct dentry *rs_sta_dbgfs_stats_table_file; -#endif - - /* used to be in sta_info */ - int last_txrate_idx; -}; - - struct iwl3945_sta_priv { - struct iwl3945_rs_sta rs_sta; + struct iwl3945_rs_sta *rs_sta; }; enum iwl3945_antenna { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c index 910217f0ad8a..d256fecc6cda 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -591,6 +591,16 @@ static void iwl5000_tx_queue_set_status(struct iwl_priv *priv, scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); } +static int iwl5000_send_wimax_coex(struct iwl_priv *priv) +{ + struct iwl_wimax_coex_cmd coex_cmd; + + memset(&coex_cmd, 0, sizeof(coex_cmd)); + + return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD, + sizeof(coex_cmd), &coex_cmd); +} + int iwl5000_alive_notify(struct iwl_priv *priv) { u32 a; @@ -671,7 +681,7 @@ int iwl5000_alive_notify(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); - iwl_send_wimax_coex(priv); + iwl5000_send_wimax_coex(priv); iwl5000_set_Xtal_calib(priv); iwl_send_calib_results(priv); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c index 70e117f8d0c4..32466d38d1ae 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -299,7 +299,7 @@ struct iwl_cfg iwl6000h_2agn_cfg = { .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_AB, .pll_cfg_val = 0, - .set_l0s = true, + .set_l0s = false, .use_bsm = false, .pa_type = IWL_PA_HYBRID, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, @@ -329,7 +329,7 @@ struct iwl_cfg iwl6000h_2abg_cfg = { .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_AB, .pll_cfg_val = 0, - .set_l0s = true, + .set_l0s = false, .use_bsm = false, .pa_type = IWL_PA_HYBRID, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, @@ -358,7 +358,7 @@ struct iwl_cfg iwl6000h_2bg_cfg = { .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_AB, .pll_cfg_val = 0, - .set_l0s = true, + .set_l0s = false, .use_bsm = false, .pa_type = IWL_PA_HYBRID, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, @@ -390,7 +390,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .valid_tx_ant = ANT_BC, .valid_rx_ant = ANT_BC, .pll_cfg_val = 0, - .set_l0s = true, + .set_l0s = false, .use_bsm = false, .pa_type = IWL_PA_INTERNAL, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, @@ -420,7 +420,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .valid_tx_ant = ANT_BC, .valid_rx_ant = ANT_BC, .pll_cfg_val = 0, - .set_l0s = true, + .set_l0s = false, .use_bsm = false, .pa_type = IWL_PA_INTERNAL, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, @@ -449,7 +449,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .valid_tx_ant = ANT_BC, .valid_rx_ant = ANT_BC, .pll_cfg_val = 0, - .set_l0s = true, + .set_l0s = false, .use_bsm = false, .pa_type = IWL_PA_INTERNAL, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, @@ -478,7 +478,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_AB, .pll_cfg_val = 0, - .set_l0s = true, + .set_l0s = false, .use_bsm = false, .pa_type = IWL_PA_SYSTEM, .max_ll_items = OTP_MAX_LL_ITEMS_6x50, @@ -490,8 +490,6 @@ struct iwl_cfg iwl6050_2agn_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, - .support_sm_ps = true, - .support_wimax_coexist = true, }; struct iwl_cfg iwl6050_2abg_cfg = { @@ -510,7 +508,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_AB, .pll_cfg_val = 0, - .set_l0s = true, + .set_l0s = false, .use_bsm = false, .pa_type = IWL_PA_SYSTEM, .max_ll_items = OTP_MAX_LL_ITEMS_6x50, @@ -521,7 +519,6 @@ struct iwl_cfg iwl6050_2abg_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, - .support_wimax_coexist = true, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -540,7 +537,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, .pll_cfg_val = 0, - .set_l0s = true, + .set_l0s = false, .use_bsm = false, .pa_type = IWL_PA_SYSTEM, .max_ll_items = OTP_MAX_LL_ITEMS_6x00, @@ -570,7 +567,7 @@ struct iwl_cfg iwl6050_3agn_cfg = { .valid_tx_ant = ANT_ABC, .valid_rx_ant = ANT_ABC, .pll_cfg_val = 0, - .set_l0s = true, + .set_l0s = false, .use_bsm = false, .pa_type = IWL_PA_SYSTEM, .max_ll_items = OTP_MAX_LL_ITEMS_6x50, @@ -582,8 +579,6 @@ struct iwl_cfg iwl6050_3agn_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, - .support_sm_ps = true, - .support_wimax_coexist = true, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 43edd8fd4405..27d4ece4d467 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2477,12 +2477,19 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta; struct iwl_station_priv *sta_priv = (struct iwl_station_priv *) sta->drv_priv; struct iwl_priv *priv; + int i, j; priv = (struct iwl_priv *)priv_rate; IWL_DEBUG_RATE(priv, "create station rate scale window\n"); lq_sta = &sta_priv->lq_sta; + lq_sta->lq.sta_id = 0xff; + + for (j = 0; j < LQ_SIZE; j++) + for (i = 0; i < IWL_RATE_COUNT; i++) + rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); + return lq_sta; } @@ -2495,12 +2502,6 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; struct iwl_lq_sta *lq_sta = priv_sta; - lq_sta->lq.sta_id = 0xff; - - for (j = 0; j < LQ_SIZE; j++) - for (i = 0; i < IWL_RATE_COUNT; i++) - rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); - lq_sta->flush_timer = 0; lq_sta->supp_rates = sta->supp_rates[sband->band]; for (j = 0; j < LQ_SIZE; j++) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c index b5fe8f87aa7e..fa1672e99e4b 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -190,7 +190,11 @@ int iwl_commit_rxon(struct iwl_priv *priv) priv->start_calib = 0; /* Add the broadcast address so we can send broadcast frames */ - iwl_add_bcast_station(priv); + if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == + IWL_INVALID_STATION) { + IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); + return -EIO; + } /* If we have set the ASSOC_MSK and we are in BSS mode then * add the IWL_AP_ID to the station rate table */ @@ -886,7 +890,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) u32 inta, handled = 0; u32 inta_fh; unsigned long flags; - u32 i; #ifdef CONFIG_IWLWIFI_DEBUG u32 inta_mask; #endif @@ -1004,17 +1007,19 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) handled |= CSR_INT_BIT_SW_ERR; } - /* - * uCode wakes up after power-down sleep. - * Tell device about any new tx or host commands enqueued, - * and about any Rx buffers made available while asleep. - */ + /* uCode wakes up after power-down sleep */ if (inta & CSR_INT_BIT_WAKEUP) { IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); iwl_rx_queue_update_write_ptr(priv, &priv->rxq); - for (i = 0; i < priv->hw_params.max_txq_num; i++) - iwl_txq_update_write_ptr(priv, &priv->txq[i]); + iwl_txq_update_write_ptr(priv, &priv->txq[0]); + iwl_txq_update_write_ptr(priv, &priv->txq[1]); + iwl_txq_update_write_ptr(priv, &priv->txq[2]); + iwl_txq_update_write_ptr(priv, &priv->txq[3]); + iwl_txq_update_write_ptr(priv, &priv->txq[4]); + iwl_txq_update_write_ptr(priv, &priv->txq[5]); + priv->isr_stats.wakeup++; + handled |= CSR_INT_BIT_WAKEUP; } @@ -1028,12 +1033,11 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); } - /* This "Tx" DMA channel is used only for loading uCode */ if (inta & CSR_INT_BIT_FH_TX) { - IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); + IWL_DEBUG_ISR(priv, "Tx interrupt\n"); priv->isr_stats.tx++; handled |= CSR_INT_BIT_FH_TX; - /* Wake up uCode load routine, now that load is complete */ + /* FH finished to write, send event */ priv->ucode_write_complete = 1; wake_up_interruptible(&priv->wait_command_queue); } @@ -1230,13 +1234,12 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) iwl_leds_background(priv); } - /* This "Tx" DMA channel is used only for loading uCode */ if (inta & CSR_INT_BIT_FH_TX) { iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_TX_MASK); - IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); + IWL_DEBUG_ISR(priv, "Tx interrupt\n"); priv->isr_stats.tx++; handled |= CSR_INT_BIT_FH_TX; - /* Wake up uCode load routine, now that load is complete */ + /* FH finished to write, send event */ priv->ucode_write_complete = 1; wake_up_interruptible(&priv->wait_command_queue); } @@ -1374,14 +1377,6 @@ static int iwl_read_ucode(struct iwl_priv *priv) IWL_UCODE_API(priv->ucode_ver), IWL_UCODE_SERIAL(priv->ucode_ver)); - snprintf(priv->hw->wiphy->fw_version, - sizeof(priv->hw->wiphy->fw_version), - "%u.%u.%u.%u", - IWL_UCODE_MAJOR(priv->ucode_ver), - IWL_UCODE_MINOR(priv->ucode_ver), - IWL_UCODE_API(priv->ucode_ver), - IWL_UCODE_SERIAL(priv->ucode_ver)); - if (build) IWL_DEBUG_INFO(priv, "Build %u\n", build); @@ -2520,7 +2515,7 @@ void iwl_config_ap(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); iwl_activate_qos(priv, 1); spin_unlock_irqrestore(&priv->lock, flags); - iwl_add_bcast_station(priv); + iwl_rxon_add_station(priv, iwl_bcast_addr, 0); } iwl_send_beacon_cmd(priv); @@ -2968,100 +2963,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) del_timer_sync(&priv->statistics_periodic); } -static void iwl_init_hw_rates(struct iwl_priv *priv, - struct ieee80211_rate *rates) -{ - int i; - - for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) { - rates[i].bitrate = iwl_rates[i].ieee * 5; - rates[i].hw_value = i; /* Rate scaling will work on indexes */ - rates[i].hw_value_short = i; - rates[i].flags = 0; - if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) { - /* - * If CCK != 1M then set short preamble rate flag. - */ - rates[i].flags |= - (iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ? - 0 : IEEE80211_RATE_SHORT_PREAMBLE; - } - } -} - -static int iwl_init_drv(struct iwl_priv *priv) -{ - int ret; - - priv->ibss_beacon = NULL; - - spin_lock_init(&priv->lock); - spin_lock_init(&priv->sta_lock); - spin_lock_init(&priv->hcmd_lock); - - INIT_LIST_HEAD(&priv->free_frames); - - mutex_init(&priv->mutex); - - /* Clear the driver's (not device's) station table */ - iwl_clear_stations_table(priv); - - priv->ieee_channels = NULL; - priv->ieee_rates = NULL; - priv->band = IEEE80211_BAND_2GHZ; - - priv->iw_mode = NL80211_IFTYPE_STATION; - if (priv->cfg->support_sm_ps) - priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DYNAMIC; - else - priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED; - - /* Choose which receivers/antennas to use */ - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - - iwl_init_scan_params(priv); - - iwl_reset_qos(priv); - - priv->qos_data.qos_active = 0; - priv->qos_data.qos_cap.val = 0; - - priv->rates_mask = IWL_RATES_MASK; - /* Set the tx_power_user_lmt to the lowest power level - * this value will get overwritten by channel max power avg - * from eeprom */ - priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN; - - ret = iwl_init_channel_map(priv); - if (ret) { - IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); - goto err; - } - - ret = iwlcore_init_geos(priv); - if (ret) { - IWL_ERR(priv, "initializing geos failed: %d\n", ret); - goto err_free_channel_map; - } - iwl_init_hw_rates(priv, priv->ieee_rates); - - return 0; - -err_free_channel_map: - iwl_free_channel_map(priv); -err: - return ret; -} - -static void iwl_uninit_drv(struct iwl_priv *priv) -{ - iwl_calib_free_results(priv); - iwlcore_free_geos(priv); - iwl_free_channel_map(priv); - kfree(priv->scan); -} - static struct attribute *iwl_sysfs_entries[] = { &dev_attr_flags.attr, &dev_attr_filter_flags.attr, @@ -3204,6 +3105,12 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_iounmap; } + /* amp init */ + err = priv->cfg->ops->lib->apm_ops.init(priv); + if (err < 0) { + IWL_ERR(priv, "Failed to init APMG\n"); + goto out_iounmap; + } /***************** * 4. Read EEPROM *****************/ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-calib.c b/trunk/drivers/net/wireless/iwlwifi/iwl-calib.c index d994de7438d8..1f801eb9fbff 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -132,7 +132,6 @@ void iwl_calib_free_results(struct iwl_priv *priv) priv->calib_results[i].buf_len = 0; } } -EXPORT_SYMBOL(iwl_calib_free_results); /***************************************************************************** * RUNTIME calibrations framework diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h b/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h index b62c90ec9e1e..954bad60355d 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -3503,134 +3503,30 @@ struct iwl_led_cmd { } __attribute__ ((packed)); /* - * station priority table entries - * also used as potential "events" value for both - * COEX_MEDIUM_NOTIFICATION and COEX_EVENT_CMD - */ - -/* - * COEX events entry flag masks - * RP - Requested Priority - * WP - Win Medium Priority: priority assigned when the contention has been won - */ -#define COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG (0x1) -#define COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG (0x2) -#define COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_FLG (0x4) - -#define COEX_CU_UNASSOC_IDLE_RP 4 -#define COEX_CU_UNASSOC_MANUAL_SCAN_RP 4 -#define COEX_CU_UNASSOC_AUTO_SCAN_RP 4 -#define COEX_CU_CALIBRATION_RP 4 -#define COEX_CU_PERIODIC_CALIBRATION_RP 4 -#define COEX_CU_CONNECTION_ESTAB_RP 4 -#define COEX_CU_ASSOCIATED_IDLE_RP 4 -#define COEX_CU_ASSOC_MANUAL_SCAN_RP 4 -#define COEX_CU_ASSOC_AUTO_SCAN_RP 4 -#define COEX_CU_ASSOC_ACTIVE_LEVEL_RP 4 -#define COEX_CU_RF_ON_RP 6 -#define COEX_CU_RF_OFF_RP 4 -#define COEX_CU_STAND_ALONE_DEBUG_RP 6 -#define COEX_CU_IPAN_ASSOC_LEVEL_RP 4 -#define COEX_CU_RSRVD1_RP 4 -#define COEX_CU_RSRVD2_RP 4 - -#define COEX_CU_UNASSOC_IDLE_WP 3 -#define COEX_CU_UNASSOC_MANUAL_SCAN_WP 3 -#define COEX_CU_UNASSOC_AUTO_SCAN_WP 3 -#define COEX_CU_CALIBRATION_WP 3 -#define COEX_CU_PERIODIC_CALIBRATION_WP 3 -#define COEX_CU_CONNECTION_ESTAB_WP 3 -#define COEX_CU_ASSOCIATED_IDLE_WP 3 -#define COEX_CU_ASSOC_MANUAL_SCAN_WP 3 -#define COEX_CU_ASSOC_AUTO_SCAN_WP 3 -#define COEX_CU_ASSOC_ACTIVE_LEVEL_WP 3 -#define COEX_CU_RF_ON_WP 3 -#define COEX_CU_RF_OFF_WP 3 -#define COEX_CU_STAND_ALONE_DEBUG_WP 6 -#define COEX_CU_IPAN_ASSOC_LEVEL_WP 3 -#define COEX_CU_RSRVD1_WP 3 -#define COEX_CU_RSRVD2_WP 3 - -#define COEX_UNASSOC_IDLE_FLAGS 0 -#define COEX_UNASSOC_MANUAL_SCAN_FLAGS \ - (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG) -#define COEX_UNASSOC_AUTO_SCAN_FLAGS \ - (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG) -#define COEX_CALIBRATION_FLAGS \ - (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG) -#define COEX_PERIODIC_CALIBRATION_FLAGS 0 -/* - * COEX_CONNECTION_ESTAB: - * we need DELAY_MEDIUM_FREE_NTFY to let WiMAX disconnect from network. - */ -#define COEX_CONNECTION_ESTAB_FLAGS \ - (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG | \ - COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_FLG) -#define COEX_ASSOCIATED_IDLE_FLAGS 0 -#define COEX_ASSOC_MANUAL_SCAN_FLAGS \ - (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG) -#define COEX_ASSOC_AUTO_SCAN_FLAGS \ - (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG) -#define COEX_ASSOC_ACTIVE_LEVEL_FLAGS 0 -#define COEX_RF_ON_FLAGS 0 -#define COEX_RF_OFF_FLAGS 0 -#define COEX_STAND_ALONE_DEBUG_FLAGS \ - (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG) -#define COEX_IPAN_ASSOC_LEVEL_FLAGS \ - (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG | \ - COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_FLG) -#define COEX_RSRVD1_FLAGS 0 -#define COEX_RSRVD2_FLAGS 0 -/* - * COEX_CU_RF_ON is the event wrapping all radio ownership. - * We need DELAY_MEDIUM_FREE_NTFY to let WiMAX disconnect from network. + * Coexistence WIFI/WIMAX Command + * COEX_PRIORITY_TABLE_CMD = 0x5a + * */ -#define COEX_CU_RF_ON_FLAGS \ - (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG | \ - COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_FLG) - - enum { - /* un-association part */ COEX_UNASSOC_IDLE = 0, COEX_UNASSOC_MANUAL_SCAN = 1, COEX_UNASSOC_AUTO_SCAN = 2, - /* calibration */ COEX_CALIBRATION = 3, COEX_PERIODIC_CALIBRATION = 4, - /* connection */ COEX_CONNECTION_ESTAB = 5, - /* association part */ COEX_ASSOCIATED_IDLE = 6, COEX_ASSOC_MANUAL_SCAN = 7, COEX_ASSOC_AUTO_SCAN = 8, COEX_ASSOC_ACTIVE_LEVEL = 9, - /* RF ON/OFF */ COEX_RF_ON = 10, COEX_RF_OFF = 11, COEX_STAND_ALONE_DEBUG = 12, - /* IPAN */ COEX_IPAN_ASSOC_LEVEL = 13, - /* reserved */ COEX_RSRVD1 = 14, COEX_RSRVD2 = 15, COEX_NUM_OF_EVENTS = 16 }; -/* - * Coexistence WIFI/WIMAX Command - * COEX_PRIORITY_TABLE_CMD = 0x5a - * - */ struct iwl_wimax_coex_event_entry { u8 request_prio; u8 win_medium_prio; @@ -3655,55 +3551,6 @@ struct iwl_wimax_coex_cmd { struct iwl_wimax_coex_event_entry sta_prio[COEX_NUM_OF_EVENTS]; } __attribute__ ((packed)); -/* - * Coexistence MEDIUM NOTIFICATION - * COEX_MEDIUM_NOTIFICATION = 0x5b - * - * notification from uCode to host to indicate medium changes - * - */ -/* - * status field - * bit 0 - 2: medium status - * bit 3: medium change indication - * bit 4 - 31: reserved - */ -/* status option values, (0 - 2 bits) */ -#define COEX_MEDIUM_BUSY (0x0) /* radio belongs to WiMAX */ -#define COEX_MEDIUM_ACTIVE (0x1) /* radio belongs to WiFi */ -#define COEX_MEDIUM_PRE_RELEASE (0x2) /* received radio release */ -#define COEX_MEDIUM_MSK (0x7) - -/* send notification status (1 bit) */ -#define COEX_MEDIUM_CHANGED (0x8) -#define COEX_MEDIUM_CHANGED_MSK (0x8) -#define COEX_MEDIUM_SHIFT (3) - -struct iwl_coex_medium_notification { - __le32 status; - __le32 events; -} __attribute__ ((packed)); - -/* - * Coexistence EVENT Command - * COEX_EVENT_CMD = 0x5c - * - * send from host to uCode for coex event request. - */ -/* flags options */ -#define COEX_EVENT_REQUEST_MSK (0x1) - -struct iwl_coex_event_cmd { - u8 flags; - u8 event; - __le16 reserved; -} __attribute__ ((packed)); - -struct iwl_coex_event_resp { - __le32 status; -} __attribute__ ((packed)); - - /****************************************************************************** * (13) * Union of all expected notifications/responses: @@ -3740,8 +3587,6 @@ struct iwl_rx_packet { struct iwl_notif_statistics stats; struct iwl_compressed_ba_resp compressed_ba; struct iwl_missed_beacon_notif missed_beacon; - struct iwl_coex_medium_notification coex_medium_notif; - struct iwl_coex_event_resp coex_event; __le32 status; u8 raw[0]; } u; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c index e0b5b4aef41d..d2b56baf98fb 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c @@ -46,37 +46,6 @@ MODULE_VERSION(IWLWIFI_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_LICENSE("GPL"); -static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { - {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, - 0, COEX_UNASSOC_IDLE_FLAGS}, - {COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP, - 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, - {COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP, - 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, - {COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP, - 0, COEX_CALIBRATION_FLAGS}, - {COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP, - 0, COEX_PERIODIC_CALIBRATION_FLAGS}, - {COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP, - 0, COEX_CONNECTION_ESTAB_FLAGS}, - {COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP, - 0, COEX_ASSOCIATED_IDLE_FLAGS}, - {COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP, - 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, - {COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP, - 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, - {COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP, - 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, - {COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS}, - {COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS}, - {COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP, - 0, COEX_STAND_ALONE_DEBUG_FLAGS}, - {COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP, - 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, - {COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS}, - {COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS} -}; - #define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \ [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ IWL_RATE_SISO_##s##M_PLCP, \ @@ -445,12 +414,8 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, if (priv->cfg->ht_greenfield_support) ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; ht_info->cap |= IEEE80211_HT_CAP_SGI_20; - if (priv->cfg->support_sm_ps) - ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & - (WLAN_HT_CAP_SM_PS_DYNAMIC << 2)); - else - ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & - (WLAN_HT_CAP_SM_PS_DISABLED << 2)); + ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & + (WLAN_HT_CAP_SM_PS_DISABLED << 2)); max_bit_rate = MAX_BIT_RATE_20_MHZ; if (priv->hw_params.ht40_channel & BIT(band)) { @@ -486,6 +451,28 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, } } +static void iwlcore_init_hw_rates(struct iwl_priv *priv, + struct ieee80211_rate *rates) +{ + int i; + + for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) { + rates[i].bitrate = iwl_rates[i].ieee * 5; + rates[i].hw_value = i; /* Rate scaling will work on indexes */ + rates[i].hw_value_short = i; + rates[i].flags = 0; + if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) { + /* + * If CCK != 1M then set short preamble rate flag. + */ + rates[i].flags |= + (iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ? + 0 : IEEE80211_RATE_SHORT_PREAMBLE; + } + } +} + + /** * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom */ @@ -998,35 +985,17 @@ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) } /* - * When we are in power saving mode, unless device support spatial - * multiplexing power save, use the active count for rx chain count. + * When we are in power saving, there's no difference between + * using multiple chains or just a single chain, but due to the + * lack of SM PS we lose a lot of throughput if we use just a + * single chain. + * + * Therefore, use the active count here (which will use multiple + * chains unless connected to a legacy AP). */ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) { - int idle_cnt = active_cnt; - bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); - - if (priv->cfg->support_sm_ps) { - /* # Rx chains when idling and maybe trying to save power */ - switch (priv->current_ht_config.sm_ps) { - case WLAN_HT_CAP_SM_PS_STATIC: - case WLAN_HT_CAP_SM_PS_DYNAMIC: - idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL : - IWL_NUM_IDLE_CHAINS_SINGLE; - break; - case WLAN_HT_CAP_SM_PS_DISABLED: - idle_cnt = (is_cam) ? active_cnt : - IWL_NUM_IDLE_CHAINS_SINGLE; - break; - case WLAN_HT_CAP_SM_PS_INVALID: - default: - IWL_ERR(priv, "invalid sm_ps mode %d\n", - priv->current_ht_config.sm_ps); - WARN_ON(1); - break; - } - } - return idle_cnt; + return active_cnt; } /* up to 4 chains */ @@ -1384,39 +1353,39 @@ EXPORT_SYMBOL(iwl_irq_handle_error); int iwl_apm_stop_master(struct iwl_priv *priv) { - int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); - /* stop device's busmaster DMA activity */ + /* set stop master bit */ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, + iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); - if (ret) - IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n"); + spin_unlock_irqrestore(&priv->lock, flags); IWL_DEBUG_INFO(priv, "stop master\n"); - return ret; + return 0; } EXPORT_SYMBOL(iwl_apm_stop_master); void iwl_apm_stop(struct iwl_priv *priv) { + unsigned long flags; + IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n"); - /* Stop device's DMA activity */ iwl_apm_stop_master(priv); - /* Reset the entire device */ + spin_lock_irqsave(&priv->lock, flags); + iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); udelay(10); - - /* - * Clear "initialization complete" bit to move adapter from - * D0A* (powered-up Active) --> D0U* (Uninitialized) state. - */ + /* clear "init complete" move adapter D0A* --> D0U state */ iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + spin_unlock_irqrestore(&priv->lock, flags); } EXPORT_SYMBOL(iwl_apm_stop); @@ -1461,12 +1430,8 @@ int iwl_apm_init(struct iwl_priv *priv) CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); /* - * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition. - * Check if BIOS (or OS) enabled L1-ASPM on this device. - * If so (likely), disable L0S, so device moves directly L0->L1; - * costs negligible amount of power savings. - * If not (unlikely), enable L0S, so there is at least some - * power savings, even without L1. + * HW bug W/A - costs negligible power consumption ... + * Check if BIOS (or OS) enabled L1-ASPM on this device */ if (priv->cfg->set_l0s) { lctl = iwl_pcie_link_ctl(priv); @@ -1602,6 +1567,68 @@ int iwl_set_hw_params(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_set_hw_params); +int iwl_init_drv(struct iwl_priv *priv) +{ + int ret; + + priv->ibss_beacon = NULL; + + spin_lock_init(&priv->lock); + spin_lock_init(&priv->sta_lock); + spin_lock_init(&priv->hcmd_lock); + + INIT_LIST_HEAD(&priv->free_frames); + + mutex_init(&priv->mutex); + + /* Clear the driver's (not device's) station table */ + iwl_clear_stations_table(priv); + + priv->ieee_channels = NULL; + priv->ieee_rates = NULL; + priv->band = IEEE80211_BAND_2GHZ; + + priv->iw_mode = NL80211_IFTYPE_STATION; + + /* Choose which receivers/antennas to use */ + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + + iwl_init_scan_params(priv); + + iwl_reset_qos(priv); + + priv->qos_data.qos_active = 0; + priv->qos_data.qos_cap.val = 0; + + priv->rates_mask = IWL_RATES_MASK; + /* Set the tx_power_user_lmt to the lowest power level + * this value will get overwritten by channel max power avg + * from eeprom */ + priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN; + + ret = iwl_init_channel_map(priv); + if (ret) { + IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); + goto err; + } + + ret = iwlcore_init_geos(priv); + if (ret) { + IWL_ERR(priv, "initializing geos failed: %d\n", ret); + goto err_free_channel_map; + } + iwlcore_init_hw_rates(priv, priv->ieee_rates); + + return 0; + +err_free_channel_map: + iwl_free_channel_map(priv); +err: + return ret; +} +EXPORT_SYMBOL(iwl_init_drv); + int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) { int ret = 0; @@ -1649,6 +1676,15 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) } EXPORT_SYMBOL(iwl_set_tx_power); +void iwl_uninit_drv(struct iwl_priv *priv) +{ + iwl_calib_free_results(priv); + iwlcore_free_geos(priv); + iwl_free_channel_map(priv); + kfree(priv->scan); +} +EXPORT_SYMBOL(iwl_uninit_drv); + #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) /* Free dram table */ @@ -2300,7 +2336,7 @@ static void iwl_ht_conf(struct iwl_priv *priv, switch (priv->iw_mode) { case NL80211_IFTYPE_STATION: rcu_read_lock(); - sta = ieee80211_find_sta(priv->vif, priv->bssid); + sta = ieee80211_find_sta(priv->hw, priv->bssid); if (sta) { struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; int maxstreams; @@ -2310,12 +2346,6 @@ static void iwl_ht_conf(struct iwl_priv *priv, >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; maxstreams += 1; - ht_conf->sm_ps = - (u8)((ht_cap->cap & IEEE80211_HT_CAP_SM_PS) - >> 2); - IWL_DEBUG_MAC80211(priv, "sm_ps: 0x%x\n", - ht_conf->sm_ps); - if ((ht_cap->mcs.rx_mask[1] == 0) && (ht_cap->mcs.rx_mask[2] == 0)) ht_conf->single_chain_sufficient = true; @@ -2896,34 +2926,6 @@ void iwl_free_txq_mem(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_free_txq_mem); -int iwl_send_wimax_coex(struct iwl_priv *priv) -{ - struct iwl_wimax_coex_cmd uninitialized_var(coex_cmd); - - if (priv->cfg->support_wimax_coexist) { - /* UnMask wake up src at associated sleep */ - coex_cmd.flags |= COEX_FLAGS_ASSOC_WA_UNMASK_MSK; - - /* UnMask wake up src at unassociated sleep */ - coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK; - memcpy(coex_cmd.sta_prio, cu_priorities, - sizeof(struct iwl_wimax_coex_event_entry) * - COEX_NUM_OF_EVENTS); - - /* enabling the coexistence feature */ - coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK; - - /* enabling the priorities tables */ - coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK; - } else { - /* coexistence is disabled */ - memset(&coex_cmd, 0, sizeof(coex_cmd)); - } - return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD, - sizeof(coex_cmd), &coex_cmd); -} -EXPORT_SYMBOL(iwl_send_wimax_coex); - #ifdef CONFIG_IWLWIFI_DEBUGFS #define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h index 9574d8f33537..b875dcfca2d6 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h @@ -228,8 +228,6 @@ struct iwl_mod_params { * @chain_noise_num_beacons: number of beacons used to compute chain noise * @adv_thermal_throttle: support advance thermal throttle * @support_ct_kill_exit: support ct kill exit condition - * @support_sm_ps: support spatial multiplexing power save - * @support_wimax_coexist: support wimax/wifi co-exist * * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the @@ -285,8 +283,6 @@ struct iwl_cfg { const bool supports_idle; bool adv_thermal_throttle; bool support_ct_kill_exit; - bool support_sm_ps; - const bool support_wimax_coexist; }; /*************************** @@ -320,6 +316,8 @@ void iwl_configure_filter(struct ieee80211_hw *hw, unsigned int *total_flags, u64 multicast); int iwl_hw_nic_init(struct iwl_priv *priv); int iwl_set_hw_params(struct iwl_priv *priv); +int iwl_init_drv(struct iwl_priv *priv); +void iwl_uninit_drv(struct iwl_priv *priv); bool iwl_is_monitor_mode(struct iwl_priv *priv); void iwl_post_associate(struct iwl_priv *priv); void iwl_bss_info_changed(struct ieee80211_hw *hw, @@ -342,7 +340,6 @@ int iwl_alloc_txq_mem(struct iwl_priv *priv); void iwl_free_txq_mem(struct iwl_priv *priv); void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, __le32 *tx_flags); -int iwl_send_wimax_coex(struct iwl_priv *priv); #ifdef CONFIG_IWLWIFI_DEBUGFS int iwl_alloc_traffic_mem(struct iwl_priv *priv); void iwl_free_traffic_mem(struct iwl_priv *priv); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h index cb2642c18da4..e7ce67387662 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -517,7 +517,6 @@ struct iwl_ht_config { bool is_ht; bool is_40mhz; bool single_chain_sufficient; - u8 sm_ps; /* BSS related data */ u8 extension_chan_offset; u8 ht_protection; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 8a0709e81a9f..9429cb1c69bd 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -533,10 +533,6 @@ int iwl_eeprom_init(struct iwl_priv *priv) goto err; } if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { - - /* OTP reads require powered-up chip */ - priv->cfg->ops->lib->apm_ops.init(priv); - ret = iwl_init_otp_access(priv); if (ret) { IWL_ERR(priv, "Failed to initialize OTP access.\n"); @@ -567,13 +563,6 @@ int iwl_eeprom_init(struct iwl_priv *priv) e[cache_addr / 2] = eeprom_data; cache_addr += sizeof(u16); } - - /* - * Now that OTP reads are complete, reset chip to save - * power until we load uCode during "up". - */ - priv->cfg->ops->lib->apm_ops.stop(priv); - } else { /* eeprom is an array of 16bit values */ for (addr = 0; addr < sz; addr += sizeof(u16)) { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 905645d15a9b..f2a60dc4109f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -55,8 +55,6 @@ const char *get_cmd_string(u8 cmd) IWL_CMD(REPLY_LEDS_CMD); IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); IWL_CMD(COEX_PRIORITY_TABLE_CMD); - IWL_CMD(COEX_MEDIUM_NOTIFICATION); - IWL_CMD(COEX_EVENT_CMD); IWL_CMD(RADAR_NOTIFICATION); IWL_CMD(REPLY_QUIET_CMD); IWL_CMD(REPLY_CHANNEL_SWITCH); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c index 1eb0d0bf1fe4..4fca65a2fe9c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -401,7 +401,6 @@ void iwl_init_scan_params(struct iwl_priv *priv) if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx; } -EXPORT_SYMBOL(iwl_init_scan_params); static int iwl_scan_initiate(struct iwl_priv *priv) { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c index eba36f737388..dc74c16d36a8 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -182,11 +182,6 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, goto done; mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; - IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n", - (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ? - "static" : - (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ? - "dynamic" : "disabled"); sta_flags = priv->stations[index].sta.station_flags; @@ -1017,7 +1012,7 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) */ if (priv->current_ht_config.is_ht) { rcu_read_lock(); - sta = ieee80211_find_sta(priv->vif, addr); + sta = ieee80211_find_sta(priv->hw, addr); if (sta) { memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config)); cur_ht_config = &ht_config; @@ -1034,68 +1029,6 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) } EXPORT_SYMBOL(iwl_rxon_add_station); -/** - * iwl_sta_init_bcast_lq - Initialize a bcast station's hardware rate table - * - * NOTE: Run REPLY_ADD_STA command to set up station table entry, before - * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, - * which requires station table entry to exist). - */ -static void iwl_sta_init_bcast_lq(struct iwl_priv *priv) -{ - int i, r; - struct iwl_link_quality_cmd link_cmd = { - .reserved1 = 0, - }; - u32 rate_flags; - - /* Set up the rate scaling to start at selected rate, fall back - * all the way down to 1M in IEEE order, and then spin on 1M */ - if (priv->band == IEEE80211_BAND_5GHZ) - r = IWL_RATE_6M_INDEX; - else - r = IWL_RATE_1M_INDEX; - - for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { - rate_flags = 0; - if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) - rate_flags |= RATE_MCS_CCK_MSK; - - rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << - RATE_MCS_ANT_POS; - - link_cmd.rs_table[i].rate_n_flags = - iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); - r = iwl_get_prev_ieee_rate(r); - } - - link_cmd.general_params.single_stream_ant_msk = - first_antenna(priv->hw_params.valid_tx_ant); - link_cmd.general_params.dual_stream_ant_msk = 3; - link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; - link_cmd.agg_params.agg_time_limit = - cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); - - /* Update the rate scaling for control frame Tx to AP */ - link_cmd.sta_id = priv->hw_params.bcast_sta_id; - - iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, - sizeof(link_cmd), &link_cmd, NULL); -} - - -/** - * iwl_add_bcast_station - add broadcast station into station table. - */ -void iwl_add_bcast_station(struct iwl_priv *priv) -{ - iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL); - - /* Set up default rate scaling table in device's station table */ - iwl_sta_init_bcast_lq(priv); -} -EXPORT_SYMBOL(iwl_add_bcast_station); - /** * iwl_get_sta_id - Find station's index within station table * diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h index 1c382de80d49..6deebade6361 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -52,7 +52,6 @@ void iwl_update_tkip_key(struct iwl_priv *priv, const u8 *addr, u32 iv32, u16 *phase1key); int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); -void iwl_add_bcast_station(struct iwl_priv *priv); int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); void iwl_clear_stations_table(struct iwl_priv *priv); int iwl_get_free_ucode_key_index(struct iwl_priv *priv); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c index 05e75109d842..8ae4c9b614e7 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -979,8 +979,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) !(cmd->flags & CMD_SIZE_HUGE)); if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { - IWL_WARN(priv, "Not sending command - %s KILL\n", - iwl_is_rfkill(priv) ? "RF" : "CT"); + IWL_DEBUG_INFO(priv, "Not sending command - RF/CT KILL\n"); return -EIO; } @@ -1122,6 +1121,11 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, return; } + pci_unmap_single(priv->pci_dev, + pci_unmap_addr(&txq->meta[cmd_idx], mapping), + pci_unmap_len(&txq->meta[cmd_idx], len), + PCI_DMA_BIDIRECTIONAL); + for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { @@ -1169,11 +1173,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; meta = &priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_index]; - pci_unmap_single(priv->pci_dev, - pci_unmap_addr(meta, mapping), - pci_unmap_len(meta, len), - PCI_DMA_BIDIRECTIONAL); - /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { meta->source->reply_page = (unsigned long)rxb_addr(rxb); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c b/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c index 23b31e6dcacd..bfd7f497157f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2160,14 +2160,6 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) IWL_UCODE_API(priv->ucode_ver), IWL_UCODE_SERIAL(priv->ucode_ver)); - snprintf(priv->hw->wiphy->fw_version, - sizeof(priv->hw->wiphy->fw_version), - "%u.%u.%u.%u", - IWL_UCODE_MAJOR(priv->ucode_ver), - IWL_UCODE_MINOR(priv->ucode_ver), - IWL_UCODE_API(priv->ucode_ver), - IWL_UCODE_SERIAL(priv->ucode_ver)); - IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", priv->ucode_ver); IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", @@ -4000,6 +3992,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e */ spin_lock_init(&priv->reg_lock); + /* amp init */ + err = priv->cfg->ops->lib->apm_ops.init(priv); + if (err < 0) { + IWL_DEBUG_INFO(priv, "Failed to init the card\n"); + goto out_iounmap; + } + /*********************** * 4. Read EEPROM * ********************/ diff --git a/trunk/drivers/net/wireless/iwmc3200wifi/Kconfig b/trunk/drivers/net/wireless/iwmc3200wifi/Kconfig index b9d34a766964..9606b3100fde 100644 --- a/trunk/drivers/net/wireless/iwmc3200wifi/Kconfig +++ b/trunk/drivers/net/wireless/iwmc3200wifi/Kconfig @@ -1,6 +1,6 @@ config IWM tristate "Intel Wireless Multicomm 3200 WiFi driver" - depends on MMC && EXPERIMENTAL + depends on MMC && WLAN_80211 && EXPERIMENTAL depends on CFG80211 select FW_LOADER select IWMC3200TOP diff --git a/trunk/drivers/net/wireless/libertas/Kconfig b/trunk/drivers/net/wireless/libertas/Kconfig index 30aa9d48d67e..8f8d75b61ea9 100644 --- a/trunk/drivers/net/wireless/libertas/Kconfig +++ b/trunk/drivers/net/wireless/libertas/Kconfig @@ -1,6 +1,6 @@ config LIBERTAS tristate "Marvell 8xxx Libertas WLAN driver support" - depends on CFG80211 + depends on WLAN_80211 && CFG80211 select WIRELESS_EXT select WEXT_SPY select LIB80211 diff --git a/trunk/drivers/net/wireless/libertas/ethtool.c b/trunk/drivers/net/wireless/libertas/ethtool.c index 53d56ab83c03..039b555e4d76 100644 --- a/trunk/drivers/net/wireless/libertas/ethtool.c +++ b/trunk/drivers/net/wireless/libertas/ethtool.c @@ -169,19 +169,16 @@ static int lbs_ethtool_set_wol(struct net_device *dev, struct lbs_private *priv = dev->ml_priv; uint32_t criteria = 0; + if (priv->wol_criteria == 0xffffffff && wol->wolopts) + return -EOPNOTSUPP; + if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY)) return -EOPNOTSUPP; - if (wol->wolopts & WAKE_UCAST) - criteria |= EHS_WAKE_ON_UNICAST_DATA; - if (wol->wolopts & WAKE_MCAST) - criteria |= EHS_WAKE_ON_MULTICAST_DATA; - if (wol->wolopts & WAKE_BCAST) - criteria |= EHS_WAKE_ON_BROADCAST_DATA; - if (wol->wolopts & WAKE_PHY) - criteria |= EHS_WAKE_ON_MAC_EVENT; - if (wol->wolopts == 0) - criteria |= EHS_REMOVE_WAKEUP; + if (wol->wolopts & WAKE_UCAST) criteria |= EHS_WAKE_ON_UNICAST_DATA; + if (wol->wolopts & WAKE_MCAST) criteria |= EHS_WAKE_ON_MULTICAST_DATA; + if (wol->wolopts & WAKE_BCAST) criteria |= EHS_WAKE_ON_BROADCAST_DATA; + if (wol->wolopts & WAKE_PHY) criteria |= EHS_WAKE_ON_MAC_EVENT; return lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL); } diff --git a/trunk/drivers/net/wireless/libertas/if_spi.c b/trunk/drivers/net/wireless/libertas/if_spi.c index d6a48dd3652c..30d9d0ea28eb 100644 --- a/trunk/drivers/net/wireless/libertas/if_spi.c +++ b/trunk/drivers/net/wireless/libertas/if_spi.c @@ -32,6 +32,12 @@ #include "dev.h" #include "if_spi.h" +struct if_spi_packet { + struct list_head list; + u16 blen; + u8 buffer[0] __attribute__((aligned(4))); +}; + struct if_spi_card { struct spi_device *spi; struct lbs_private *priv; @@ -60,10 +66,33 @@ struct if_spi_card { struct semaphore spi_thread_terminated; u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; + + /* A buffer of incoming packets from libertas core. + * Since we can't sleep in hw_host_to_card, we have to buffer + * them. */ + struct list_head cmd_packet_list; + struct list_head data_packet_list; + + /* Protects cmd_packet_list and data_packet_list */ + spinlock_t buffer_lock; }; static void free_if_spi_card(struct if_spi_card *card) { + struct list_head *cursor, *next; + struct if_spi_packet *packet; + + BUG_ON(card->run_thread); + list_for_each_safe(cursor, next, &card->cmd_packet_list) { + packet = container_of(cursor, struct if_spi_packet, list); + list_del(&packet->list); + kfree(packet); + } + list_for_each_safe(cursor, next, &card->data_packet_list) { + packet = container_of(cursor, struct if_spi_packet, list); + list_del(&packet->list); + kfree(packet); + } spi_set_drvdata(card->spi, NULL); kfree(card); } @@ -745,6 +774,40 @@ static int if_spi_c2h_data(struct if_spi_card *card) return err; } +/* Move data or a command from the host to the card. */ +static void if_spi_h2c(struct if_spi_card *card, + struct if_spi_packet *packet, int type) +{ + int err = 0; + u16 int_type, port_reg; + + switch (type) { + case MVMS_DAT: + int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER; + port_reg = IF_SPI_DATA_RDWRPORT_REG; + break; + case MVMS_CMD: + int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER; + port_reg = IF_SPI_CMD_RDWRPORT_REG; + break; + default: + lbs_pr_err("can't transfer buffer of type %d\n", type); + err = -EINVAL; + goto out; + } + + /* Write the data to the card */ + err = spu_write(card, port_reg, packet->buffer, packet->blen); + if (err) + goto out; + +out: + kfree(packet); + + if (err) + lbs_pr_err("%s: error %d\n", __func__, err); +} + /* Inform the host about a card event */ static void if_spi_e2h(struct if_spi_card *card) { @@ -774,6 +837,8 @@ static int lbs_spi_thread(void *data) int err; struct if_spi_card *card = data; u16 hiStatus; + unsigned long flags; + struct if_spi_packet *packet; while (1) { /* Wait to be woken up by one of two things. First, our ISR @@ -812,9 +877,43 @@ static int lbs_spi_thread(void *data) if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY || (card->priv->psstate != PS_STATE_FULL_POWER && (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) { + /* This means two things. First of all, + * if there was a previous command sent, the card has + * successfully received it. + * Secondly, it is now ready to download another + * command. + */ lbs_host_to_card_done(card->priv); + + /* Do we have any command packets from the host to + * send? */ + packet = NULL; + spin_lock_irqsave(&card->buffer_lock, flags); + if (!list_empty(&card->cmd_packet_list)) { + packet = (struct if_spi_packet *)(card-> + cmd_packet_list.next); + list_del(&packet->list); + } + spin_unlock_irqrestore(&card->buffer_lock, flags); + + if (packet) + if_spi_h2c(card, packet, MVMS_CMD); } + if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) { + /* Do we have any data packets from the host to + * send? */ + packet = NULL; + spin_lock_irqsave(&card->buffer_lock, flags); + if (!list_empty(&card->data_packet_list)) { + packet = (struct if_spi_packet *)(card-> + data_packet_list.next); + list_del(&packet->list); + } + spin_unlock_irqrestore(&card->buffer_lock, flags); + if (packet) + if_spi_h2c(card, packet, MVMS_DAT); + } if (hiStatus & IF_SPI_HIST_CARD_EVENT) if_spi_e2h(card); @@ -843,18 +942,40 @@ static int if_spi_host_to_card(struct lbs_private *priv, u8 type, u8 *buf, u16 nb) { int err = 0; + unsigned long flags; struct if_spi_card *card = priv->card; + struct if_spi_packet *packet; + u16 blen; lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); - nb = ALIGN(nb, 4); + if (nb == 0) { + lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb); + err = -EINVAL; + goto out; + } + blen = ALIGN(nb, 4); + packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC); + if (!packet) { + err = -ENOMEM; + goto out; + } + packet->blen = blen; + memcpy(packet->buffer, buf, nb); + memset(packet->buffer + nb, 0, blen - nb); switch (type) { case MVMS_CMD: - err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, buf, nb); + priv->dnld_sent = DNLD_CMD_SENT; + spin_lock_irqsave(&card->buffer_lock, flags); + list_add_tail(&packet->list, &card->cmd_packet_list); + spin_unlock_irqrestore(&card->buffer_lock, flags); break; case MVMS_DAT: - err = spu_write(card, IF_SPI_DATA_RDWRPORT_REG, buf, nb); + priv->dnld_sent = DNLD_DATA_SENT; + spin_lock_irqsave(&card->buffer_lock, flags); + list_add_tail(&packet->list, &card->data_packet_list); + spin_unlock_irqrestore(&card->buffer_lock, flags); break; default: lbs_pr_err("can't transfer buffer of type %d", type); @@ -862,6 +983,9 @@ static int if_spi_host_to_card(struct lbs_private *priv, break; } + /* Wake up the spi thread */ + up(&card->spi_ready); +out: lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err); return err; } @@ -938,6 +1062,9 @@ static int __devinit if_spi_probe(struct spi_device *spi) sema_init(&card->spi_ready, 0); sema_init(&card->spi_thread_terminated, 0); + INIT_LIST_HEAD(&card->cmd_packet_list); + INIT_LIST_HEAD(&card->data_packet_list); + spin_lock_init(&card->buffer_lock); /* Initialize the SPI Interface Unit */ err = spu_init(card, pdata->use_dummy_writes); @@ -1014,9 +1141,6 @@ static int __devinit if_spi_probe(struct spi_device *spi) goto terminate_thread; } - /* poke the IRQ handler so that we don't miss the first interrupt */ - up(&card->spi_ready); - /* Start the card. * This will call register_netdev, and we'll start * getting interrupts... */ diff --git a/trunk/drivers/net/wireless/libertas/if_usb.c b/trunk/drivers/net/wireless/libertas/if_usb.c index f12d667ba100..a8262dea9b1f 100644 --- a/trunk/drivers/net/wireless/libertas/if_usb.c +++ b/trunk/drivers/net/wireless/libertas/if_usb.c @@ -511,7 +511,7 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, /* Fill the receive configuration URB and initialise the Rx call back */ usb_fill_bulk_urb(cardp->rx_urb, cardp->udev, usb_rcvbulkpipe(cardp->udev, cardp->ep_in), - skb->data + IPFIELD_ALIGN_OFFSET, + (void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET), MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp); diff --git a/trunk/drivers/net/wireless/mac80211_hwsim.c b/trunk/drivers/net/wireless/mac80211_hwsim.c index fc4ec48eda12..38cfd79e0590 100644 --- a/trunk/drivers/net/wireless/mac80211_hwsim.c +++ b/trunk/drivers/net/wireless/mac80211_hwsim.c @@ -284,7 +284,7 @@ struct mac80211_hwsim_data { struct ieee80211_channel *channel; unsigned long beacon_int; /* in jiffies unit */ unsigned int rx_filter; - bool started, idle; + int started; struct timer_list beacon_timer; enum ps_mode { PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL @@ -365,49 +365,6 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, } -static void mac80211_hwsim_monitor_ack(struct ieee80211_hw *hw, const u8 *addr) -{ - struct mac80211_hwsim_data *data = hw->priv; - struct sk_buff *skb; - struct hwsim_radiotap_hdr *hdr; - u16 flags; - struct ieee80211_hdr *hdr11; - - if (!netif_running(hwsim_mon)) - return; - - skb = dev_alloc_skb(100); - if (skb == NULL) - return; - - hdr = (struct hwsim_radiotap_hdr *) skb_put(skb, sizeof(*hdr)); - hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION; - hdr->hdr.it_pad = 0; - hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr)); - hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | - (1 << IEEE80211_RADIOTAP_CHANNEL)); - hdr->rt_flags = 0; - hdr->rt_rate = 0; - hdr->rt_channel = cpu_to_le16(data->channel->center_freq); - flags = IEEE80211_CHAN_2GHZ; - hdr->rt_chbitmask = cpu_to_le16(flags); - - hdr11 = (struct ieee80211_hdr *) skb_put(skb, 10); - hdr11->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | - IEEE80211_STYPE_ACK); - hdr11->duration_id = cpu_to_le16(0); - memcpy(hdr11->addr1, addr, ETH_ALEN); - - skb->dev = hwsim_mon; - skb_set_mac_header(skb, 0); - skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = htons(ETH_P_802_2); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx(skb); -} - - static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data, struct sk_buff *skb) { @@ -445,12 +402,6 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_rx_status rx_status; - if (data->idle) { - printk(KERN_DEBUG "%s: Trying to TX when idle - reject\n", - wiphy_name(hw->wiphy)); - return false; - } - memset(&rx_status, 0, sizeof(rx_status)); /* TODO: set mactime */ rx_status.freq = data->channel->center_freq; @@ -477,8 +428,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, if (data == data2) continue; - if (data2->idle || !data2->started || - !hwsim_ps_rx_ok(data2, skb) || + if (!data2->started || !hwsim_ps_rx_ok(data2, skb) || !data->channel || !data2->channel || data->channel->center_freq != data2->channel->center_freq || !(data->group & data2->group)) @@ -514,10 +464,6 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) } ack = mac80211_hwsim_tx_frame(hw, skb); - if (ack && skb->len >= 16) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - mac80211_hwsim_monitor_ack(hw, hdr->addr2); - } txi = IEEE80211_SKB_CB(skb); @@ -625,8 +571,6 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) !!(conf->flags & IEEE80211_CONF_IDLE), !!(conf->flags & IEEE80211_CONF_PS)); - data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); - data->channel = conf->channel; if (!data->started || !data->beacon_int) del_timer(&data->beacon_timer); @@ -1101,20 +1045,19 @@ static int __init init_mac80211_hwsim(void) sband->channels = data->channels_2ghz; sband->n_channels = ARRAY_SIZE(hwsim_channels_2ghz); - sband->bitrates = data->rates; - sband->n_bitrates = ARRAY_SIZE(hwsim_rates); break; case IEEE80211_BAND_5GHZ: sband->channels = data->channels_5ghz; sband->n_channels = ARRAY_SIZE(hwsim_channels_5ghz); - sband->bitrates = data->rates + 4; - sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4; break; default: break; } + sband->bitrates = data->rates; + sband->n_bitrates = ARRAY_SIZE(hwsim_rates); + sband->ht_cap.ht_supported = true; sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_GRN_FLD | diff --git a/trunk/drivers/net/wireless/mwl8k.c b/trunk/drivers/net/wireless/mwl8k.c index 2ebfee4da3fa..746532ebe5a8 100644 --- a/trunk/drivers/net/wireless/mwl8k.c +++ b/trunk/drivers/net/wireless/mwl8k.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -28,6 +27,18 @@ #define MWL8K_NAME KBUILD_MODNAME #define MWL8K_VERSION "0.10" +MODULE_DESCRIPTION(MWL8K_DESC); +MODULE_VERSION(MWL8K_VERSION); +MODULE_AUTHOR("Lennert Buytenhek "); +MODULE_LICENSE("GPL"); + +static DEFINE_PCI_DEVICE_TABLE(mwl8k_table) = { + { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = 8687, }, + { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = 8687, }, + { } +}; +MODULE_DEVICE_TABLE(pci, mwl8k_table); + /* Register definitions */ #define MWL8K_HIU_GEN_PTR 0x00000c10 #define MWL8K_MODE_STA 0x0000005a @@ -77,89 +88,72 @@ MWL8K_A2H_INT_RX_READY | \ MWL8K_A2H_INT_TX_DONE) +/* WME stream classes */ +#define WME_AC_BE 0 /* best effort */ +#define WME_AC_BK 1 /* background */ +#define WME_AC_VI 2 /* video */ +#define WME_AC_VO 3 /* voice */ + #define MWL8K_RX_QUEUES 1 #define MWL8K_TX_QUEUES 4 -struct rxd_ops { - int rxd_size; - 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); -}; - -struct mwl8k_device_info { - char *part_name; - char *helper_image; - char *fw_image; - struct rxd_ops *rxd_ops; - u16 modes; -}; - struct mwl8k_rx_queue { - int rxd_count; + int rx_desc_count; /* hw receives here */ - int head; + int rx_head; /* refill descs here */ - int tail; + int rx_tail; - void *rxd; - dma_addr_t rxd_dma; - struct { - struct sk_buff *skb; - DECLARE_PCI_UNMAP_ADDR(dma) - } *buf; + struct mwl8k_rx_desc *rx_desc_area; + dma_addr_t rx_desc_dma; + struct sk_buff **rx_skb; }; struct mwl8k_tx_queue { /* hw transmits here */ - int head; + int tx_head; /* sw appends here */ - int tail; + int tx_tail; - struct ieee80211_tx_queue_stats stats; - struct mwl8k_tx_desc *txd; - dma_addr_t txd_dma; - struct sk_buff **skb; + struct ieee80211_tx_queue_stats tx_stats; + struct mwl8k_tx_desc *tx_desc_area; + dma_addr_t tx_desc_dma; + struct sk_buff **tx_skb; }; /* Pointers to the firmware data and meta information about it. */ struct mwl8k_firmware { - /* Boot helper code */ - struct firmware *helper; - /* Microcode */ struct firmware *ucode; + + /* Boot helper code */ + struct firmware *helper; }; struct mwl8k_priv { - void __iomem *sram; void __iomem *regs; struct ieee80211_hw *hw; struct pci_dev *pdev; - - struct mwl8k_device_info *device_info; - bool ap_fw; - struct rxd_ops *rxd_ops; + u8 name[16]; /* firmware files and meta data */ struct mwl8k_firmware fw; + u32 part_num; /* firmware access */ struct mutex fw_mutex; struct task_struct *fw_mutex_owner; int fw_mutex_depth; + struct completion *tx_wait; struct completion *hostcmd_wait; /* lock held over TX and TX reap */ spinlock_t tx_lock; - /* TX quiesce completion, protected by fw_mutex and tx_lock */ - struct completion *tx_wait; - struct ieee80211_vif *vif; struct ieee80211_channel *current_channel; @@ -184,11 +178,10 @@ struct mwl8k_priv { /* PHY parameters */ struct ieee80211_supported_band band; struct ieee80211_channel channels[14]; - struct ieee80211_rate rates[13]; + struct ieee80211_rate rates[12]; bool radio_on; bool radio_short_preamble; - bool sniffer_enabled; bool wmm_enabled; /* XXX need to convert this to handle multiple interfaces */ @@ -206,6 +199,9 @@ struct mwl8k_priv { /* Tasklet to reclaim TX descriptors and buffers after tx */ struct tasklet_struct tx_reclaim_task; + + /* Work thread to serialize configuration requests */ + struct workqueue_struct *config_wq; }; /* Per interface specific private data */ @@ -224,7 +220,7 @@ struct mwl8k_vif { * Subset of supported legacy rates. * Intersection of AP and STA supported rates. */ - struct ieee80211_rate legacy_rates[13]; + struct ieee80211_rate legacy_rates[12]; /* number of supported legacy rates */ u8 legacy_nrates; @@ -256,10 +252,9 @@ static const struct ieee80211_rate mwl8k_rates[] = { { .bitrate = 10, .hw_value = 2, }, { .bitrate = 20, .hw_value = 4, }, { .bitrate = 55, .hw_value = 11, }, - { .bitrate = 110, .hw_value = 22, }, - { .bitrate = 220, .hw_value = 44, }, { .bitrate = 60, .hw_value = 12, }, { .bitrate = 90, .hw_value = 18, }, + { .bitrate = 110, .hw_value = 22, }, { .bitrate = 120, .hw_value = 24, }, { .bitrate = 180, .hw_value = 36, }, { .bitrate = 240, .hw_value = 48, }, @@ -275,12 +270,10 @@ static const struct ieee80211_rate mwl8k_rates[] = { /* Firmware command codes */ #define MWL8K_CMD_CODE_DNLD 0x0001 #define MWL8K_CMD_GET_HW_SPEC 0x0003 -#define MWL8K_CMD_SET_HW_SPEC 0x0004 #define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010 #define MWL8K_CMD_GET_STAT 0x0014 #define MWL8K_CMD_RADIO_CONTROL 0x001c #define MWL8K_CMD_RF_TX_POWER 0x001e -#define MWL8K_CMD_RF_ANTENNA 0x0020 #define MWL8K_CMD_SET_PRE_SCAN 0x0107 #define MWL8K_CMD_SET_POST_SCAN 0x0108 #define MWL8K_CMD_SET_RF_CHANNEL 0x010a @@ -294,7 +287,6 @@ static const struct ieee80211_rate mwl8k_rates[] = { #define MWL8K_CMD_MIMO_CONFIG 0x0125 #define MWL8K_CMD_USE_FIXED_RATE 0x0126 #define MWL8K_CMD_ENABLE_SNIFFER 0x0150 -#define MWL8K_CMD_SET_MAC_ADDR 0x0202 #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 #define MWL8K_CMD_UPDATE_STADB 0x1123 @@ -307,12 +299,10 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) switch (cmd & ~0x8000) { MWL8K_CMDNAME(CODE_DNLD); MWL8K_CMDNAME(GET_HW_SPEC); - MWL8K_CMDNAME(SET_HW_SPEC); MWL8K_CMDNAME(MAC_MULTICAST_ADR); MWL8K_CMDNAME(GET_STAT); MWL8K_CMDNAME(RADIO_CONTROL); MWL8K_CMDNAME(RF_TX_POWER); - MWL8K_CMDNAME(RF_ANTENNA); MWL8K_CMDNAME(SET_PRE_SCAN); MWL8K_CMDNAME(SET_POST_SCAN); MWL8K_CMDNAME(SET_RF_CHANNEL); @@ -326,7 +316,6 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) MWL8K_CMDNAME(MIMO_CONFIG); MWL8K_CMDNAME(USE_FIXED_RATE); MWL8K_CMDNAME(ENABLE_SNIFFER); - MWL8K_CMDNAME(SET_MAC_ADDR); MWL8K_CMDNAME(SET_RATEADAPT_MODE); MWL8K_CMDNAME(UPDATE_STADB); default: @@ -364,35 +353,41 @@ static void mwl8k_release_firmware(struct mwl8k_priv *priv) /* Request fw image */ static int mwl8k_request_fw(struct mwl8k_priv *priv, - const char *fname, struct firmware **fw) + const char *fname, struct firmware **fw) { /* release current image */ if (*fw != NULL) mwl8k_release_fw(fw); return request_firmware((const struct firmware **)fw, - fname, &priv->pdev->dev); + fname, &priv->pdev->dev); } -static int mwl8k_request_firmware(struct mwl8k_priv *priv) +static int mwl8k_request_firmware(struct mwl8k_priv *priv, u32 part_num) { - struct mwl8k_device_info *di = priv->device_info; + u8 filename[64]; int rc; - if (di->helper_image != NULL) { - rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw.helper); - if (rc) { - printk(KERN_ERR "%s: Error requesting helper " - "firmware file %s\n", pci_name(priv->pdev), - di->helper_image); - return rc; - } + priv->part_num = part_num; + + snprintf(filename, sizeof(filename), + "mwl8k/helper_%u.fw", priv->part_num); + + rc = mwl8k_request_fw(priv, filename, &priv->fw.helper); + if (rc) { + printk(KERN_ERR + "%s Error requesting helper firmware file %s\n", + pci_name(priv->pdev), filename); + return rc; } - rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw.ucode); + snprintf(filename, sizeof(filename), + "mwl8k/fmimage_%u.fw", priv->part_num); + + rc = mwl8k_request_fw(priv, filename, &priv->fw.ucode); if (rc) { - printk(KERN_ERR "%s: Error requesting firmware file %s\n", - pci_name(priv->pdev), di->fw_image); + printk(KERN_ERR "%s Error requesting firmware file %s\n", + pci_name(priv->pdev), filename); mwl8k_release_fw(&priv->fw.helper); return rc; } @@ -439,7 +434,6 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) break; } - cond_resched(); udelay(1); } while (--loops); @@ -548,62 +542,43 @@ static int mwl8k_feed_fw_image(struct mwl8k_priv *priv, return rc; } -static int mwl8k_load_firmware(struct ieee80211_hw *hw) +static int mwl8k_load_firmware(struct mwl8k_priv *priv) { - struct mwl8k_priv *priv = hw->priv; - struct firmware *fw = priv->fw.ucode; - struct mwl8k_device_info *di = priv->device_info; - int rc; - int loops; - - if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { - struct firmware *helper = priv->fw.helper; + int loops, rc; - if (helper == NULL) { - printk(KERN_ERR "%s: helper image needed but none " - "given\n", pci_name(priv->pdev)); - return -EINVAL; - } + const u8 *ucode = priv->fw.ucode->data; + size_t ucode_len = priv->fw.ucode->size; + const u8 *helper = priv->fw.helper->data; + size_t helper_len = priv->fw.helper->size; - rc = mwl8k_load_fw_image(priv, helper->data, helper->size); + if (!memcmp(ucode, "\x01\x00\x00\x00", 4)) { + rc = mwl8k_load_fw_image(priv, helper, helper_len); if (rc) { printk(KERN_ERR "%s: unable to load firmware " - "helper image\n", pci_name(priv->pdev)); + "helper image\n", pci_name(priv->pdev)); return rc; } msleep(1); - rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); + rc = mwl8k_feed_fw_image(priv, ucode, ucode_len); } else { - rc = mwl8k_load_fw_image(priv, fw->data, fw->size); + rc = mwl8k_load_fw_image(priv, ucode, ucode_len); } if (rc) { - printk(KERN_ERR "%s: unable to load firmware image\n", - pci_name(priv->pdev)); + printk(KERN_ERR "%s: unable to load firmware data\n", + pci_name(priv->pdev)); return rc; } - if (di->modes & BIT(NL80211_IFTYPE_AP)) - iowrite32(MWL8K_MODE_AP, priv->regs + MWL8K_HIU_GEN_PTR); - else - iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); + iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); msleep(1); loops = 200000; do { - u32 ready_code; - - ready_code = ioread32(priv->regs + MWL8K_HIU_INT_CODE); - if (ready_code == MWL8K_FWAP_READY) { - priv->ap_fw = 1; + if (ioread32(priv->regs + MWL8K_HIU_INT_CODE) + == MWL8K_FWSTA_READY) break; - } else if (ready_code == MWL8K_FWSTA_READY) { - priv->ap_fw = 0; - break; - } - - cond_resched(); udelay(1); } while (--loops); @@ -630,7 +605,7 @@ struct ewc_ht_info { /* Peer Entry flags - used to define the type of the peer node */ #define MWL8K_PEER_TYPE_ACCESSPOINT 2 -#define MWL8K_IEEE_LEGACY_DATA_RATES 13 +#define MWL8K_IEEE_LEGACY_DATA_RATES 12 #define MWL8K_MCS_BITMAP_SIZE 16 struct peer_capability_info { @@ -756,96 +731,16 @@ static inline void mwl8k_add_dma_header(struct sk_buff *skb) /* - * Packet reception for 88w8366. + * Packet reception. */ -struct mwl8k_rxd_8366 { - __le16 pkt_len; - __u8 sq2; - __u8 rate; - __le32 pkt_phys_addr; - __le32 next_rxd_phys_addr; - __le16 qos_control; - __le16 htsig2; - __le32 hw_rssi_info; - __le32 hw_noise_floor_info; - __u8 noise_floor; - __u8 pad0[3]; - __u8 rssi; - __u8 rx_status; - __u8 channel; - __u8 rx_ctrl; -} __attribute__((packed)); +#define MWL8K_RX_CTRL_OWNED_BY_HOST 0x02 -#define MWL8K_8366_RX_CTRL_OWNED_BY_HOST 0x80 - -static void mwl8k_rxd_8366_init(void *_rxd, dma_addr_t next_dma_addr) -{ - struct mwl8k_rxd_8366 *rxd = _rxd; - - rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); - rxd->rx_ctrl = MWL8K_8366_RX_CTRL_OWNED_BY_HOST; -} - -static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len) -{ - struct mwl8k_rxd_8366 *rxd = _rxd; - - rxd->pkt_len = cpu_to_le16(len); - rxd->pkt_phys_addr = cpu_to_le32(addr); - wmb(); - rxd->rx_ctrl = 0; -} - -static int -mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status) -{ - struct mwl8k_rxd_8366 *rxd = _rxd; - - if (!(rxd->rx_ctrl & MWL8K_8366_RX_CTRL_OWNED_BY_HOST)) - return -1; - rmb(); - - memset(status, 0, sizeof(*status)); - - status->signal = -rxd->rssi; - status->noise = -rxd->noise_floor; - - if (rxd->rate & 0x80) { - status->flag |= RX_FLAG_HT; - status->rate_idx = rxd->rate & 0x7f; - } else { - int i; - - for (i = 0; i < ARRAY_SIZE(mwl8k_rates); i++) { - if (mwl8k_rates[i].hw_value == rxd->rate) { - status->rate_idx = i; - break; - } - } - } - - status->band = IEEE80211_BAND_2GHZ; - status->freq = ieee80211_channel_to_frequency(rxd->channel); - - return le16_to_cpu(rxd->pkt_len); -} - -static struct rxd_ops rxd_8366_ops = { - .rxd_size = sizeof(struct mwl8k_rxd_8366), - .rxd_init = mwl8k_rxd_8366_init, - .rxd_refill = mwl8k_rxd_8366_refill, - .rxd_process = mwl8k_rxd_8366_process, -}; - -/* - * Packet reception for 88w8687. - */ -struct mwl8k_rxd_8687 { +struct mwl8k_rx_desc { __le16 pkt_len; __u8 link_quality; __u8 noise_level; __le32 pkt_phys_addr; - __le32 next_rxd_phys_addr; + __le32 next_rx_desc_phys_addr; __le16 qos_control; __le16 rate_info; __le32 pad0[4]; @@ -857,76 +752,6 @@ struct mwl8k_rxd_8687 { __u8 pad2[2]; } __attribute__((packed)); -#define MWL8K_8687_RATE_INFO_SHORTPRE 0x8000 -#define MWL8K_8687_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3) -#define MWL8K_8687_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f) -#define MWL8K_8687_RATE_INFO_40MHZ 0x0004 -#define MWL8K_8687_RATE_INFO_SHORTGI 0x0002 -#define MWL8K_8687_RATE_INFO_MCS_FORMAT 0x0001 - -#define MWL8K_8687_RX_CTRL_OWNED_BY_HOST 0x02 - -static void mwl8k_rxd_8687_init(void *_rxd, dma_addr_t next_dma_addr) -{ - struct mwl8k_rxd_8687 *rxd = _rxd; - - rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); - rxd->rx_ctrl = MWL8K_8687_RX_CTRL_OWNED_BY_HOST; -} - -static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len) -{ - struct mwl8k_rxd_8687 *rxd = _rxd; - - rxd->pkt_len = cpu_to_le16(len); - rxd->pkt_phys_addr = cpu_to_le32(addr); - wmb(); - rxd->rx_ctrl = 0; -} - -static int -mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status) -{ - struct mwl8k_rxd_8687 *rxd = _rxd; - u16 rate_info; - - if (!(rxd->rx_ctrl & MWL8K_8687_RX_CTRL_OWNED_BY_HOST)) - return -1; - rmb(); - - rate_info = le16_to_cpu(rxd->rate_info); - - memset(status, 0, sizeof(*status)); - - status->signal = -rxd->rssi; - status->noise = -rxd->noise_level; - status->qual = rxd->link_quality; - status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info); - status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info); - - if (rate_info & MWL8K_8687_RATE_INFO_SHORTPRE) - status->flag |= RX_FLAG_SHORTPRE; - if (rate_info & MWL8K_8687_RATE_INFO_40MHZ) - status->flag |= RX_FLAG_40MHZ; - if (rate_info & MWL8K_8687_RATE_INFO_SHORTGI) - status->flag |= RX_FLAG_SHORT_GI; - if (rate_info & MWL8K_8687_RATE_INFO_MCS_FORMAT) - status->flag |= RX_FLAG_HT; - - status->band = IEEE80211_BAND_2GHZ; - status->freq = ieee80211_channel_to_frequency(rxd->channel); - - return le16_to_cpu(rxd->pkt_len); -} - -static struct rxd_ops rxd_8687_ops = { - .rxd_size = sizeof(struct mwl8k_rxd_8687), - .rxd_init = mwl8k_rxd_8687_init, - .rxd_refill = mwl8k_rxd_8687_refill, - .rxd_process = mwl8k_rxd_8687_process, -}; - - #define MWL8K_RX_DESCS 256 #define MWL8K_RX_MAXSZ 3800 @@ -937,44 +762,43 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index) int size; int i; - rxq->rxd_count = 0; - rxq->head = 0; - rxq->tail = 0; + rxq->rx_desc_count = 0; + rxq->rx_head = 0; + rxq->rx_tail = 0; - size = MWL8K_RX_DESCS * priv->rxd_ops->rxd_size; + size = MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc); - rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma); - if (rxq->rxd == NULL) { + rxq->rx_desc_area = + pci_alloc_consistent(priv->pdev, size, &rxq->rx_desc_dma); + if (rxq->rx_desc_area == NULL) { printk(KERN_ERR "%s: failed to alloc RX descriptors\n", - wiphy_name(hw->wiphy)); + priv->name); return -ENOMEM; } - memset(rxq->rxd, 0, size); + memset(rxq->rx_desc_area, 0, size); - rxq->buf = kmalloc(MWL8K_RX_DESCS * sizeof(*rxq->buf), GFP_KERNEL); - if (rxq->buf == NULL) { + rxq->rx_skb = kmalloc(MWL8K_RX_DESCS * + sizeof(*rxq->rx_skb), GFP_KERNEL); + if (rxq->rx_skb == NULL) { printk(KERN_ERR "%s: failed to alloc RX skbuff list\n", - wiphy_name(hw->wiphy)); - pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma); + priv->name); + pci_free_consistent(priv->pdev, size, + rxq->rx_desc_area, rxq->rx_desc_dma); return -ENOMEM; } - memset(rxq->buf, 0, MWL8K_RX_DESCS * sizeof(*rxq->buf)); + memset(rxq->rx_skb, 0, MWL8K_RX_DESCS * sizeof(*rxq->rx_skb)); for (i = 0; i < MWL8K_RX_DESCS; i++) { - int desc_size; - void *rxd; + struct mwl8k_rx_desc *rx_desc; int nexti; - dma_addr_t next_dma_addr; - desc_size = priv->rxd_ops->rxd_size; - rxd = rxq->rxd + (i * priv->rxd_ops->rxd_size); + rx_desc = rxq->rx_desc_area + i; + nexti = (i + 1) % MWL8K_RX_DESCS; - nexti = i + 1; - if (nexti == MWL8K_RX_DESCS) - nexti = 0; - next_dma_addr = rxq->rxd_dma + (nexti * desc_size); - - priv->rxd_ops->rxd_init(rxd, next_dma_addr); + rx_desc->next_rx_desc_phys_addr = + cpu_to_le32(rxq->rx_desc_dma + + nexti * sizeof(*rx_desc)); + rx_desc->rx_ctrl = MWL8K_RX_CTRL_OWNED_BY_HOST; } return 0; @@ -987,28 +811,27 @@ static int rxq_refill(struct ieee80211_hw *hw, int index, int limit) int refilled; refilled = 0; - while (rxq->rxd_count < MWL8K_RX_DESCS && limit--) { + while (rxq->rx_desc_count < MWL8K_RX_DESCS && limit--) { struct sk_buff *skb; - dma_addr_t addr; int rx; - void *rxd; skb = dev_alloc_skb(MWL8K_RX_MAXSZ); if (skb == NULL) break; - addr = pci_map_single(priv->pdev, skb->data, - MWL8K_RX_MAXSZ, DMA_FROM_DEVICE); + rxq->rx_desc_count++; + + rx = rxq->rx_tail; + rxq->rx_tail = (rx + 1) % MWL8K_RX_DESCS; - rxq->rxd_count++; - rx = rxq->tail++; - if (rxq->tail == MWL8K_RX_DESCS) - rxq->tail = 0; - rxq->buf[rx].skb = skb; - pci_unmap_addr_set(&rxq->buf[rx], dma, addr); + rxq->rx_desc_area[rx].pkt_phys_addr = + cpu_to_le32(pci_map_single(priv->pdev, skb->data, + MWL8K_RX_MAXSZ, DMA_FROM_DEVICE)); - rxd = rxq->rxd + (rx * priv->rxd_ops->rxd_size); - priv->rxd_ops->rxd_refill(rxd, addr, MWL8K_RX_MAXSZ); + rxq->rx_desc_area[rx].pkt_len = cpu_to_le16(MWL8K_RX_MAXSZ); + rxq->rx_skb[rx] = skb; + wmb(); + rxq->rx_desc_area[rx].rx_ctrl = 0; refilled++; } @@ -1024,24 +847,24 @@ static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index) int i; for (i = 0; i < MWL8K_RX_DESCS; i++) { - if (rxq->buf[i].skb != NULL) { - pci_unmap_single(priv->pdev, - pci_unmap_addr(&rxq->buf[i], dma), - MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); - pci_unmap_addr_set(&rxq->buf[i], dma, 0); - - kfree_skb(rxq->buf[i].skb); - rxq->buf[i].skb = NULL; + if (rxq->rx_skb[i] != NULL) { + unsigned long addr; + + addr = le32_to_cpu(rxq->rx_desc_area[i].pkt_phys_addr); + pci_unmap_single(priv->pdev, addr, MWL8K_RX_MAXSZ, + PCI_DMA_FROMDEVICE); + kfree_skb(rxq->rx_skb[i]); + rxq->rx_skb[i] = NULL; } } - kfree(rxq->buf); - rxq->buf = NULL; + kfree(rxq->rx_skb); + rxq->rx_skb = NULL; pci_free_consistent(priv->pdev, - MWL8K_RX_DESCS * priv->rxd_ops->rxd_size, - rxq->rxd, rxq->rxd_dma); - rxq->rxd = NULL; + MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc), + rxq->rx_desc_area, rxq->rx_desc_dma); + rxq->rx_desc_area = NULL; } @@ -1057,11 +880,9 @@ mwl8k_capture_bssid(struct mwl8k_priv *priv, struct ieee80211_hdr *wh) !compare_ether_addr(wh->addr3, priv->capture_bssid); } -static inline void mwl8k_save_beacon(struct ieee80211_hw *hw, - struct sk_buff *skb) +static inline void mwl8k_save_beacon(struct mwl8k_priv *priv, + struct sk_buff *skb) { - struct mwl8k_priv *priv = hw->priv; - priv->capture_beacon = false; memset(priv->capture_bssid, 0, ETH_ALEN); @@ -1072,7 +893,8 @@ static inline void mwl8k_save_beacon(struct ieee80211_hw *hw, */ priv->beacon_skb = skb_copy(skb, GFP_ATOMIC); if (priv->beacon_skb != NULL) - ieee80211_queue_work(hw, &priv->finalize_join_worker); + queue_work(priv->config_wq, + &priv->finalize_join_worker); } static int rxq_process(struct ieee80211_hw *hw, int index, int limit) @@ -1082,46 +904,53 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) int processed; processed = 0; - while (rxq->rxd_count && limit--) { + while (rxq->rx_desc_count && limit--) { + struct mwl8k_rx_desc *rx_desc; struct sk_buff *skb; - void *rxd; - int pkt_len; struct ieee80211_rx_status status; + unsigned long addr; + struct ieee80211_hdr *wh; - skb = rxq->buf[rxq->head].skb; - if (skb == NULL) + rx_desc = rxq->rx_desc_area + rxq->rx_head; + if (!(rx_desc->rx_ctrl & MWL8K_RX_CTRL_OWNED_BY_HOST)) break; + rmb(); - rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size); - - pkt_len = priv->rxd_ops->rxd_process(rxd, &status); - if (pkt_len < 0) + skb = rxq->rx_skb[rxq->rx_head]; + if (skb == NULL) break; + rxq->rx_skb[rxq->rx_head] = NULL; - rxq->buf[rxq->head].skb = NULL; + rxq->rx_head = (rxq->rx_head + 1) % MWL8K_RX_DESCS; + rxq->rx_desc_count--; - pci_unmap_single(priv->pdev, - pci_unmap_addr(&rxq->buf[rxq->head], dma), - MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); - pci_unmap_addr_set(&rxq->buf[rxq->head], dma, 0); + addr = le32_to_cpu(rx_desc->pkt_phys_addr); + pci_unmap_single(priv->pdev, addr, + MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); - rxq->head++; - if (rxq->head == MWL8K_RX_DESCS) - rxq->head = 0; - - rxq->rxd_count--; - - skb_put(skb, pkt_len); + skb_put(skb, le16_to_cpu(rx_desc->pkt_len)); mwl8k_remove_dma_header(skb); + wh = (struct ieee80211_hdr *)skb->data; + /* - * Check for a pending join operation. Save a - * copy of the beacon and schedule a tasklet to - * send a FINALIZE_JOIN command to the firmware. + * Check for pending join operation. save a copy of + * the beacon and schedule a tasklet to send finalize + * join command to the firmware. */ - if (mwl8k_capture_bssid(priv, (void *)skb->data)) - mwl8k_save_beacon(hw, skb); - + if (mwl8k_capture_bssid(priv, wh)) + mwl8k_save_beacon(priv, skb); + + memset(&status, 0, sizeof(status)); + status.mactime = 0; + status.signal = -rx_desc->rssi; + status.noise = -rx_desc->noise_level; + status.qual = rx_desc->link_quality; + status.antenna = 1; + status.rate_idx = 1; + status.flag = 0; + status.band = IEEE80211_BAND_2GHZ; + status.freq = ieee80211_channel_to_frequency(rx_desc->channel); memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); ieee80211_rx_irqsafe(hw, skb); @@ -1136,10 +965,24 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) * Packet transmission. */ +/* Transmit queue assignment. */ +enum { + MWL8K_WME_AC_BK = 0, /* background access */ + MWL8K_WME_AC_BE = 1, /* best effort access */ + MWL8K_WME_AC_VI = 2, /* video access */ + MWL8K_WME_AC_VO = 3, /* voice access */ +}; + /* Transmit packet ACK policy */ #define MWL8K_TXD_ACK_POLICY_NORMAL 0 #define MWL8K_TXD_ACK_POLICY_BLOCKACK 3 +#define GET_TXQ(_ac) (\ + ((_ac) == WME_AC_VO) ? MWL8K_WME_AC_VO : \ + ((_ac) == WME_AC_VI) ? MWL8K_WME_AC_VI : \ + ((_ac) == WME_AC_BK) ? MWL8K_WME_AC_BK : \ + MWL8K_WME_AC_BE) + #define MWL8K_TXD_STATUS_OK 0x00000001 #define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 #define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 @@ -1154,7 +997,7 @@ struct mwl8k_tx_desc { __le32 pkt_phys_addr; __le16 pkt_len; __u8 dest_MAC_addr[ETH_ALEN]; - __le32 next_txd_phys_addr; + __le32 next_tx_desc_phys_addr; __le32 reserved; __le16 rate_info; __u8 peer_id; @@ -1170,40 +1013,44 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) int size; int i; - memset(&txq->stats, 0, sizeof(struct ieee80211_tx_queue_stats)); - txq->stats.limit = MWL8K_TX_DESCS; - txq->head = 0; - txq->tail = 0; + memset(&txq->tx_stats, 0, sizeof(struct ieee80211_tx_queue_stats)); + txq->tx_stats.limit = MWL8K_TX_DESCS; + txq->tx_head = 0; + txq->tx_tail = 0; size = MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc); - txq->txd = pci_alloc_consistent(priv->pdev, size, &txq->txd_dma); - if (txq->txd == NULL) { + txq->tx_desc_area = + pci_alloc_consistent(priv->pdev, size, &txq->tx_desc_dma); + if (txq->tx_desc_area == NULL) { printk(KERN_ERR "%s: failed to alloc TX descriptors\n", - wiphy_name(hw->wiphy)); + priv->name); return -ENOMEM; } - memset(txq->txd, 0, size); + memset(txq->tx_desc_area, 0, size); - txq->skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->skb), GFP_KERNEL); - if (txq->skb == NULL) { + txq->tx_skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->tx_skb), + GFP_KERNEL); + if (txq->tx_skb == NULL) { printk(KERN_ERR "%s: failed to alloc TX skbuff list\n", - wiphy_name(hw->wiphy)); - pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma); + priv->name); + pci_free_consistent(priv->pdev, size, + txq->tx_desc_area, txq->tx_desc_dma); return -ENOMEM; } - memset(txq->skb, 0, MWL8K_TX_DESCS * sizeof(*txq->skb)); + memset(txq->tx_skb, 0, MWL8K_TX_DESCS * sizeof(*txq->tx_skb)); for (i = 0; i < MWL8K_TX_DESCS; i++) { struct mwl8k_tx_desc *tx_desc; int nexti; - tx_desc = txq->txd + i; + tx_desc = txq->tx_desc_area + i; nexti = (i + 1) % MWL8K_TX_DESCS; tx_desc->status = 0; - tx_desc->next_txd_phys_addr = - cpu_to_le32(txq->txd_dma + nexti * sizeof(*tx_desc)); + tx_desc->next_tx_desc_phys_addr = + cpu_to_le32(txq->tx_desc_dma + + nexti * sizeof(*tx_desc)); } return 0; @@ -1218,6 +1065,11 @@ static inline void mwl8k_tx_start(struct mwl8k_priv *priv) ioread32(priv->regs + MWL8K_HIU_INT_CODE); } +static inline int mwl8k_txq_busy(struct mwl8k_priv *priv) +{ + return priv->pending_tx_pkts; +} + struct mwl8k_txq_info { u32 fw_owned; u32 drv_owned; @@ -1237,13 +1089,14 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv, memset(txinfo, 0, MWL8K_TX_QUEUES * sizeof(struct mwl8k_txq_info)); + spin_lock_bh(&priv->tx_lock); for (count = 0; count < MWL8K_TX_QUEUES; count++) { txq = priv->txq + count; - txinfo[count].len = txq->stats.len; - txinfo[count].head = txq->head; - txinfo[count].tail = txq->tail; + txinfo[count].len = txq->tx_stats.len; + txinfo[count].head = txq->tx_head; + txinfo[count].tail = txq->tx_tail; for (desc = 0; desc < MWL8K_TX_DESCS; desc++) { - tx_desc = txq->txd + desc; + tx_desc = txq->tx_desc_area + desc; status = le32_to_cpu(tx_desc->status); if (status & MWL8K_TXD_STATUS_FW_OWNED) @@ -1255,26 +1108,30 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv, txinfo[count].unused++; } } + spin_unlock_bh(&priv->tx_lock); return ndescs; } /* - * Must be called with priv->fw_mutex held and tx queues stopped. + * Must be called with hw->fw_mutex held and tx queues stopped. */ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; - DECLARE_COMPLETION_ONSTACK(tx_wait); + DECLARE_COMPLETION_ONSTACK(cmd_wait); u32 count; unsigned long timeout; might_sleep(); spin_lock_bh(&priv->tx_lock); - count = priv->pending_tx_pkts; - if (count) - priv->tx_wait = &tx_wait; + count = mwl8k_txq_busy(priv); + if (count) { + priv->tx_wait = &cmd_wait; + if (priv->radio_on) + mwl8k_tx_start(priv); + } spin_unlock_bh(&priv->tx_lock); if (count) { @@ -1282,23 +1139,23 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) int index; int newcount; - timeout = wait_for_completion_timeout(&tx_wait, + timeout = wait_for_completion_timeout(&cmd_wait, msecs_to_jiffies(5000)); if (timeout) return 0; spin_lock_bh(&priv->tx_lock); priv->tx_wait = NULL; - newcount = priv->pending_tx_pkts; - mwl8k_scan_tx_ring(priv, txinfo); + newcount = mwl8k_txq_busy(priv); spin_unlock_bh(&priv->tx_lock); printk(KERN_ERR "%s(%u) TIMEDOUT:5000ms Pend:%u-->%u\n", __func__, __LINE__, count, newcount); + mwl8k_scan_tx_ring(priv, txinfo); for (index = 0; index < MWL8K_TX_QUEUES; index++) - printk(KERN_ERR "TXQ:%u L:%u H:%u T:%u FW:%u " - "DRV:%u U:%u\n", + printk(KERN_ERR + "TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n", index, txinfo[index].len, txinfo[index].head, @@ -1324,7 +1181,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) struct mwl8k_tx_queue *txq = priv->txq + index; int wake = 0; - while (txq->stats.len > 0) { + while (txq->tx_stats.len > 0) { int tx; struct mwl8k_tx_desc *tx_desc; unsigned long addr; @@ -1333,8 +1190,8 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) struct ieee80211_tx_info *info; u32 status; - tx = txq->head; - tx_desc = txq->txd + tx; + tx = txq->tx_head; + tx_desc = txq->tx_desc_area + tx; status = le32_to_cpu(tx_desc->status); @@ -1345,15 +1202,15 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) ~cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED); } - txq->head = (tx + 1) % MWL8K_TX_DESCS; - BUG_ON(txq->stats.len == 0); - txq->stats.len--; + txq->tx_head = (tx + 1) % MWL8K_TX_DESCS; + BUG_ON(txq->tx_stats.len == 0); + txq->tx_stats.len--; priv->pending_tx_pkts--; addr = le32_to_cpu(tx_desc->pkt_phys_addr); size = le16_to_cpu(tx_desc->pkt_len); - skb = txq->skb[tx]; - txq->skb[tx] = NULL; + skb = txq->tx_skb[tx]; + txq->tx_skb[tx] = NULL; BUG_ON(skb == NULL); pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE); @@ -1386,13 +1243,13 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index) mwl8k_txq_reclaim(hw, index, 1); - kfree(txq->skb); - txq->skb = NULL; + kfree(txq->tx_skb); + txq->tx_skb = NULL; pci_free_consistent(priv->pdev, MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc), - txq->txd, txq->txd_dma); - txq->txd = NULL; + txq->tx_desc_area, txq->tx_desc_dma); + txq->tx_desc_area = NULL; } static int @@ -1460,7 +1317,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) 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)); + "dropping TX frame.\n", priv->name); dev_kfree_skb(skb); return NETDEV_TX_OK; } @@ -1469,10 +1326,10 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) txq = priv->txq + index; - BUG_ON(txq->skb[txq->tail] != NULL); - txq->skb[txq->tail] = skb; + BUG_ON(txq->tx_skb[txq->tx_tail] != NULL); + txq->tx_skb[txq->tx_tail] = skb; - tx = txq->txd + txq->tail; + tx = txq->tx_desc_area + txq->tx_tail; tx->data_rate = txdatarate; tx->tx_priority = index; tx->qos_control = cpu_to_le16(qos); @@ -1483,15 +1340,15 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) wmb(); tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); - txq->stats.count++; - txq->stats.len++; + txq->tx_stats.count++; + txq->tx_stats.len++; priv->pending_tx_pkts++; - txq->tail++; - if (txq->tail == MWL8K_TX_DESCS) - txq->tail = 0; + txq->tx_tail++; + if (txq->tx_tail == MWL8K_TX_DESCS) + txq->tx_tail = 0; - if (txq->head == txq->tail) + if (txq->tx_head == txq->tx_tail) ieee80211_stop_queue(hw, index); mwl8k_tx_start(priv); @@ -1574,7 +1431,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 = 0xFFFF; dma_size = le16_to_cpu(cmd->length); dma_addr = pci_map_single(priv->pdev, cmd, dma_size, PCI_DMA_BIDIRECTIONAL); @@ -1607,7 +1464,7 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) if (!timeout) { printk(KERN_ERR "%s: Command %s timeout after %u ms\n", - wiphy_name(hw->wiphy), + priv->name, mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), MWL8K_CMD_TIMEOUT_MS); rc = -ETIMEDOUT; @@ -1615,7 +1472,7 @@ 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), + priv->name, mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), le16_to_cpu(cmd->result)); } @@ -1624,9 +1481,9 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) } /* - * CMD_GET_HW_SPEC (STA version). + * GET_HW_SPEC. */ -struct mwl8k_cmd_get_hw_spec_sta { +struct mwl8k_cmd_get_hw_spec { struct mwl8k_cmd_pkt header; __u8 hw_rev; __u8 host_interface; @@ -1642,13 +1499,13 @@ struct mwl8k_cmd_get_hw_spec_sta { __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; __le32 caps2; __le32 num_tx_desc_per_queue; - __le32 total_rxd; + __le32 total_rx_desc; } __attribute__((packed)); -static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) +static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_get_hw_spec_sta *cmd; + struct mwl8k_cmd_get_hw_spec *cmd; int rc; int i; @@ -1661,12 +1518,12 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr)); cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); - cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma); + cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rx_desc_dma); cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); for (i = 0; i < MWL8K_TX_QUEUES; i++) - cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma); + cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].tx_desc_dma); cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); - cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); + cmd->total_rx_desc = cpu_to_le32(MWL8K_RX_DESCS); rc = mwl8k_post_cmd(hw, &cmd->header); @@ -1681,129 +1538,6 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) return rc; } -/* - * CMD_GET_HW_SPEC (AP version). - */ -struct mwl8k_cmd_get_hw_spec_ap { - struct mwl8k_cmd_pkt header; - __u8 hw_rev; - __u8 host_interface; - __le16 num_wcb; - __le16 num_mcaddrs; - __u8 perm_addr[ETH_ALEN]; - __le16 region_code; - __le16 num_antenna; - __le32 fw_rev; - __le32 wcbbase0; - __le32 rxwrptr; - __le32 rxrdptr; - __le32 ps_cookie; - __le32 wcbbase1; - __le32 wcbbase2; - __le32 wcbbase3; -} __attribute__((packed)); - -static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_get_hw_spec_ap *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_HW_SPEC); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr)); - cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); - - rc = mwl8k_post_cmd(hw, &cmd->header); - - if (!rc) { - int off; - - SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr); - priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); - priv->fw_rev = le32_to_cpu(cmd->fw_rev); - priv->hw_rev = cmd->hw_rev; - - off = le32_to_cpu(cmd->wcbbase0) & 0xffff; - iowrite32(cpu_to_le32(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); - - off = le32_to_cpu(cmd->rxrdptr) & 0xffff; - iowrite32(cpu_to_le32(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); - - off = le32_to_cpu(cmd->wcbbase2) & 0xffff; - iowrite32(cpu_to_le32(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); - } - - kfree(cmd); - return rc; -} - -/* - * CMD_SET_HW_SPEC. - */ -struct mwl8k_cmd_set_hw_spec { - struct mwl8k_cmd_pkt header; - __u8 hw_rev; - __u8 host_interface; - __le16 num_mcaddrs; - __u8 perm_addr[ETH_ALEN]; - __le16 region_code; - __le32 fw_rev; - __le32 ps_cookie; - __le32 caps; - __le32 rx_queue_ptr; - __le32 num_tx_queues; - __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; - __le32 flags; - __le32 num_tx_desc_per_queue; - __le32 total_rxd; -} __attribute__((packed)); - -#define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 - -static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_set_hw_spec *cmd; - int rc; - int i; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_HW_SPEC); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); - cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma); - cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); - for (i = 0; i < MWL8K_TX_QUEUES; i++) - cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma); - cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT); - cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); - cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - /* * CMD_MAC_MULTICAST_ADR. */ @@ -1814,23 +1548,19 @@ struct mwl8k_cmd_mac_multicast_adr { __u8 addr[0][ETH_ALEN]; }; -#define MWL8K_ENABLE_RX_DIRECTED 0x0001 -#define MWL8K_ENABLE_RX_MULTICAST 0x0002 -#define MWL8K_ENABLE_RX_ALL_MULTICAST 0x0004 -#define MWL8K_ENABLE_RX_BROADCAST 0x0008 +#define MWL8K_ENABLE_RX_MULTICAST 0x000F static struct mwl8k_cmd_pkt * -__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, +__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int mc_count, struct dev_addr_list *mclist) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_cmd_mac_multicast_adr *cmd; int size; + int i; - if (allmulti || mc_count > priv->num_mcaddrs) { - allmulti = 1; - mc_count = 0; - } + if (mc_count > priv->num_mcaddrs) + mc_count = priv->num_mcaddrs; size = sizeof(*cmd) + mc_count * ETH_ALEN; @@ -1840,24 +1570,16 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR); cmd->header.length = cpu_to_le16(size); - cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_DIRECTED | - MWL8K_ENABLE_RX_BROADCAST); - - if (allmulti) { - cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_ALL_MULTICAST); - } else if (mc_count) { - int i; - - cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); - cmd->numaddr = cpu_to_le16(mc_count); - for (i = 0; i < mc_count && mclist; i++) { - if (mclist->da_addrlen != ETH_ALEN) { - kfree(cmd); - return NULL; - } - memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN); - mclist = mclist->next; + cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); + cmd->numaddr = cpu_to_le16(mc_count); + + for (i = 0; i < mc_count && mclist; i++) { + if (mclist->da_addrlen != ETH_ALEN) { + kfree(cmd); + return NULL; } + memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN); + mclist = mclist->next; } return &cmd->header; @@ -1868,6 +1590,7 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, */ struct mwl8k_cmd_802_11_get_stat { struct mwl8k_cmd_pkt header; + __le16 action; __le32 stats[64]; } __attribute__((packed)); @@ -1888,6 +1611,7 @@ static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw, cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_STAT); cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le16(MWL8K_CMD_GET); rc = mwl8k_post_cmd(hw, &cmd->header); if (!rc) { @@ -2002,39 +1726,6 @@ static int mwl8k_cmd_802_11_rf_tx_power(struct ieee80211_hw *hw, int dBm) return rc; } -/* - * CMD_RF_ANTENNA. - */ -struct mwl8k_cmd_rf_antenna { - struct mwl8k_cmd_pkt header; - __le16 antenna; - __le16 mode; -} __attribute__((packed)); - -#define MWL8K_RF_ANTENNA_RX 1 -#define MWL8K_RF_ANTENNA_TX 2 - -static int -mwl8k_cmd_rf_antenna(struct ieee80211_hw *hw, int antenna, int mask) -{ - struct mwl8k_cmd_rf_antenna *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_RF_ANTENNA); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->antenna = cpu_to_le16(antenna); - cmd->mode = cpu_to_le16(mask); - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - /* * CMD_SET_PRE_SCAN. */ @@ -2212,46 +1903,6 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) return rc; } -/* - * CMD_SET_MAC_ADDR. - */ -struct mwl8k_cmd_set_mac_addr { - struct mwl8k_cmd_pkt header; - union { - struct { - __le16 mac_type; - __u8 mac_addr[ETH_ALEN]; - } mbss; - __u8 mac_addr[ETH_ALEN]; - }; -} __attribute__((packed)); - -static int mwl8k_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_set_mac_addr *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - if (priv->ap_fw) { - cmd->mbss.mac_type = 0; - memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN); - } else { - memcpy(cmd->mac_addr, mac, ETH_ALEN); - } - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - - /* * CMD_SET_RATEADAPT_MODE. */ @@ -2354,34 +2005,17 @@ struct mwl8k_cmd_set_edca_params { /* TX opportunity in units of 32 us */ __le16 txop; - union { - struct { - /* Log exponent of max contention period: 0...15 */ - __le32 log_cw_max; - - /* Log exponent of min contention period: 0...15 */ - __le32 log_cw_min; - - /* Adaptive interframe spacing in units of 32us */ - __u8 aifs; - - /* TX queue to configure */ - __u8 txq; - } ap; - struct { - /* Log exponent of max contention period: 0...15 */ - __u8 log_cw_max; + /* Log exponent of max contention period: 0...15*/ + __u8 log_cw_max; - /* Log exponent of min contention period: 0...15 */ - __u8 log_cw_min; + /* Log exponent of min contention period: 0...15 */ + __u8 log_cw_min; - /* Adaptive interframe spacing in units of 32us */ - __u8 aifs; + /* Adaptive interframe spacing in units of 32us */ + __u8 aifs; - /* TX queue to configure */ - __u8 txq; - } sta; - }; + /* TX queue to configure */ + __u8 txq; } __attribute__((packed)); #define MWL8K_SET_EDCA_CW 0x01 @@ -2397,7 +2031,6 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, __u16 cw_min, __u16 cw_max, __u8 aifs, __u16 txop) { - struct mwl8k_priv *priv = hw->priv; struct mwl8k_cmd_set_edca_params *cmd; int rc; @@ -2405,27 +2038,14 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, if (cmd == NULL) return -ENOMEM; - /* - * Queues 0 (BE) and 1 (BK) are swapped in hardware for - * this call. - */ - qnum ^= !(qnum >> 1); - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS); cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL); cmd->txop = cpu_to_le16(txop); - if (priv->ap_fw) { - cmd->ap.log_cw_max = cpu_to_le32(ilog2(cw_max + 1)); - cmd->ap.log_cw_min = cpu_to_le32(ilog2(cw_min + 1)); - cmd->ap.aifs = aifs; - cmd->ap.txq = qnum; - } else { - cmd->sta.log_cw_max = (u8)ilog2(cw_max + 1); - cmd->sta.log_cw_min = (u8)ilog2(cw_min + 1); - cmd->sta.aifs = aifs; - cmd->sta.txq = qnum; - } + cmd->log_cw_max = (u8)ilog2(cw_max + 1); + cmd->log_cw_min = (u8)ilog2(cw_min + 1); + cmd->aifs = aifs; + cmd->txq = qnum; rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2473,8 +2093,8 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, /* XXX TBD Might just have to abort and return an error */ if (payload_len > MWL8K_FJ_BEACON_MAXLEN) printk(KERN_ERR "%s(): WARNING: Incomplete beacon " - "sent to firmware. Sz=%u MAX=%u\n", __func__, - payload_len, MWL8K_FJ_BEACON_MAXLEN); + "sent to firmware. Sz=%u MAX=%u\n", __func__, + payload_len, MWL8K_FJ_BEACON_MAXLEN); if (payload_len > MWL8K_FJ_BEACON_MAXLEN) payload_len = MWL8K_FJ_BEACON_MAXLEN; @@ -2721,10 +2341,9 @@ static int mwl8k_cmd_use_fixed_rate(struct ieee80211_hw *hw, cmd->rate_type = cpu_to_le32(rate_type); if (rate_table != NULL) { - /* - * Copy over each field manually so that endian - * conversion can be done. - */ + /* Copy over each field manually so + * that bitflipping can be done + */ cmd->rate_table.allow_rate_drop = cpu_to_le32(rate_table->allow_rate_drop); cmd->rate_table.num_rates = @@ -2780,7 +2399,7 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) if (status & MWL8K_A2H_INT_QUEUE_EMPTY) { if (!mutex_is_locked(&priv->fw_mutex) && - priv->radio_on && priv->pending_tx_pkts) + priv->radio_on && mwl8k_txq_busy(priv)) mwl8k_tx_start(priv); } @@ -2799,7 +2418,7 @@ static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (priv->current_channel == NULL) { printk(KERN_DEBUG "%s: dropped TX frame since radio " - "disabled\n", wiphy_name(hw->wiphy)); + "disabled\n", priv->name); dev_kfree_skb(skb); return NETDEV_TX_OK; } @@ -2818,7 +2437,7 @@ static int mwl8k_start(struct ieee80211_hw *hw) IRQF_SHARED, MWL8K_NAME, hw); if (rc) { printk(KERN_ERR "%s: failed to register IRQ handler\n", - wiphy_name(hw->wiphy)); + priv->name); return -EIO; } @@ -2832,17 +2451,12 @@ static int mwl8k_start(struct ieee80211_hw *hw) if (!rc) { rc = mwl8k_cmd_802_11_radio_enable(hw); - if (!priv->ap_fw) { - if (!rc) - rc = mwl8k_enable_sniffer(hw, 0); - - if (!rc) - rc = mwl8k_cmd_set_pre_scan(hw); + if (!rc) + rc = mwl8k_cmd_set_pre_scan(hw); - if (!rc) - rc = mwl8k_cmd_set_post_scan(hw, - "\x00\x00\x00\x00\x00\x00"); - } + if (!rc) + rc = mwl8k_cmd_set_post_scan(hw, + "\x00\x00\x00\x00\x00\x00"); if (!rc) rc = mwl8k_cmd_setrateadaptmode(hw, 0); @@ -2850,6 +2464,9 @@ static int mwl8k_start(struct ieee80211_hw *hw) if (!rc) rc = mwl8k_set_wmm(hw, 0); + if (!rc) + rc = mwl8k_enable_sniffer(hw, 0); + mwl8k_fw_unlock(hw); } @@ -2883,6 +2500,9 @@ static void mwl8k_stop(struct ieee80211_hw *hw) /* Stop tx reclaim tasklet */ tasklet_disable(&priv->tx_reclaim_task); + /* Stop config thread */ + flush_workqueue(priv->config_wq); + /* Return all skbs to mac80211 */ for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_reclaim(hw, i, 1); @@ -2906,24 +2526,11 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, if (conf->type != NL80211_IFTYPE_STATION) return -EINVAL; - /* - * Reject interface creation if sniffer mode is active, as - * STA operation is mutually exclusive with hardware sniffer - * mode. - */ - if (priv->sniffer_enabled) { - printk(KERN_INFO "%s: unable to create STA " - "interface due to sniffer mode being enabled\n", - wiphy_name(hw->wiphy)); - return -EINVAL; - } - /* Clean out driver private area */ mwl8k_vif = MWL8K_VIF(conf->vif); memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); - /* Set and save the mac address */ - mwl8k_set_mac_addr(hw, conf->mac_addr); + /* Save the mac address */ memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN); /* Back pointer to parent config block */ @@ -2951,8 +2558,6 @@ static void mwl8k_remove_interface(struct ieee80211_hw *hw, if (priv->vif == NULL) return; - mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); - priv->vif = NULL; } @@ -2988,13 +2593,8 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) if (rc) goto out; - if (priv->ap_fw) { - rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x7); - if (!rc) - rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_TX, 0x7); - } else { - rc = mwl8k_cmd_mimo_config(hw, 0x7, 0x7); - } + if (mwl8k_cmd_mimo_config(hw, 0x7, 0x7)) + rc = -EINVAL; out: mwl8k_fw_unlock(hw); @@ -3081,108 +2681,32 @@ static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, { struct mwl8k_cmd_pkt *cmd; - /* - * Synthesize and return a command packet that programs the - * hardware multicast address filter. At this point we don't - * know whether FIF_ALLMULTI is being requested, but if it is, - * we'll end up throwing this packet away and creating a new - * one in mwl8k_configure_filter(). - */ - cmd = __mwl8k_cmd_mac_multicast_adr(hw, 0, mc_count, mclist); + cmd = __mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist); return (unsigned long)cmd; } -static int -mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags) -{ - struct mwl8k_priv *priv = hw->priv; - - /* - * Hardware sniffer mode is mutually exclusive with STA - * operation, so refuse to enable sniffer mode if a STA - * interface is active. - */ - if (priv->vif != NULL) { - if (net_ratelimit()) - printk(KERN_INFO "%s: not enabling sniffer " - "mode because STA interface is active\n", - wiphy_name(hw->wiphy)); - return 0; - } - - if (!priv->sniffer_enabled) { - if (mwl8k_enable_sniffer(hw, 1)) - return 0; - priv->sniffer_enabled = true; - } - - *total_flags &= FIF_PROMISC_IN_BSS | FIF_ALLMULTI | - FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL | - FIF_OTHER_BSS; - - return 1; -} - static void mwl8k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, u64 multicast) { struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_pkt *cmd = (void *)(unsigned long)multicast; - - /* - * AP firmware doesn't allow fine-grained control over - * the receive filter. - */ - if (priv->ap_fw) { - *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC; - kfree(cmd); - return; - } - - /* - * Enable hardware sniffer mode if FIF_CONTROL or - * FIF_OTHER_BSS is requested. - */ - if (*total_flags & (FIF_CONTROL | FIF_OTHER_BSS) && - mwl8k_configure_filter_sniffer(hw, changed_flags, total_flags)) { - kfree(cmd); - return; - } + struct mwl8k_cmd_pkt *multicast_adr_cmd; /* Clear unsupported feature flags */ - *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC; + *total_flags &= FIF_BCN_PRBRESP_PROMISC; if (mwl8k_fw_lock(hw)) return; - if (priv->sniffer_enabled) { - mwl8k_enable_sniffer(hw, 0); - priv->sniffer_enabled = false; - } - if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { - if (*total_flags & FIF_BCN_PRBRESP_PROMISC) { - /* - * Disable the BSS filter. - */ + if (*total_flags & FIF_BCN_PRBRESP_PROMISC) mwl8k_cmd_set_pre_scan(hw); - } else { + else { u8 *bssid; - /* - * Enable the BSS filter. - * - * If there is an active STA interface, use that - * interface's BSSID, otherwise use a dummy one - * (where the OUI part needs to be nonzero for - * the BSSID to be accepted by POST_SCAN). - */ - bssid = "\x01\x00\x00\x00\x00\x00"; + bssid = "\x00\x00\x00\x00\x00\x00"; if (priv->vif != NULL) bssid = MWL8K_VIF(priv->vif)->bssid; @@ -3190,20 +2714,10 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, } } - /* - * If FIF_ALLMULTI is being requested, throw away the command - * packet that ->prepare_multicast() built and replace it with - * a command packet that enables reception of all multicast - * packets. - */ - if (*total_flags & FIF_ALLMULTI) { - kfree(cmd); - cmd = __mwl8k_cmd_mac_multicast_adr(hw, 1, 0, NULL); - } - - if (cmd != NULL) { - mwl8k_post_cmd(hw, cmd); - kfree(cmd); + multicast_adr_cmd = (void *)(unsigned long)multicast; + if (multicast_adr_cmd != NULL) { + mwl8k_post_cmd(hw, multicast_adr_cmd); + kfree(multicast_adr_cmd); } mwl8k_fw_unlock(hw); @@ -3248,7 +2762,7 @@ static int mwl8k_get_tx_stats(struct ieee80211_hw *hw, spin_lock_bh(&priv->tx_lock); for (index = 0; index < MWL8K_TX_QUEUES; index++) { txq = priv->txq + index; - memcpy(&stats[index], &txq->stats, + memcpy(&stats[index], &txq->tx_stats, sizeof(struct ieee80211_tx_queue_stats)); } spin_unlock_bh(&priv->tx_lock); @@ -3288,7 +2802,7 @@ static void mwl8k_tx_reclaim_handler(unsigned long data) for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_reclaim(hw, i, 0); - if (priv->tx_wait != NULL && !priv->pending_tx_pkts) { + if (priv->tx_wait != NULL && mwl8k_txq_busy(priv) == 0) { complete(priv->tx_wait); priv->tx_wait = NULL; } @@ -3308,36 +2822,6 @@ static void mwl8k_finalize_join_worker(struct work_struct *work) priv->beacon_skb = NULL; } -enum { - MWL8687 = 0, - MWL8366, -}; - -static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { - { - .part_name = "88w8687", - .helper_image = "mwl8k/helper_8687.fw", - .fw_image = "mwl8k/fmimage_8687.fw", - .rxd_ops = &rxd_8687_ops, - .modes = BIT(NL80211_IFTYPE_STATION), - }, - { - .part_name = "88w8366", - .helper_image = "mwl8k/helper_8366.fw", - .fw_image = "mwl8k/fmimage_8366.fw", - .rxd_ops = &rxd_8366_ops, - .modes = 0, - }, -}; - -static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { - { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, }, - { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, }, - { PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, }, - { }, -}; -MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); - static int __devinit mwl8k_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -3378,34 +2862,17 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv = hw->priv; priv->hw = hw; priv->pdev = pdev; - priv->device_info = &mwl8k_info_tbl[id->driver_data]; - priv->rxd_ops = priv->device_info->rxd_ops; - priv->sniffer_enabled = false; priv->wmm_enabled = false; priv->pending_tx_pkts = 0; + strncpy(priv->name, MWL8K_NAME, sizeof(priv->name)); SET_IEEE80211_DEV(hw, &pdev->dev); pci_set_drvdata(pdev, hw); - priv->sram = pci_iomap(pdev, 0, 0x10000); - if (priv->sram == NULL) { - printk(KERN_ERR "%s: Cannot map device SRAM\n", - wiphy_name(hw->wiphy)); - goto err_iounmap; - } - - /* - * If BAR0 is a 32 bit BAR, the register BAR will be BAR1. - * If BAR0 is a 64 bit BAR, the register BAR will be BAR2. - */ priv->regs = pci_iomap(pdev, 1, 0x10000); 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)); - goto err_iounmap; - } + printk(KERN_ERR "%s: Cannot map device memory\n", priv->name); + goto err_iounmap; } memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels)); @@ -3430,7 +2897,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, hw->queues = MWL8K_TX_QUEUES; - hw->wiphy->interface_modes = priv->device_info->modes; + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); /* Set rssi and noise values to dBm */ hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; @@ -3449,6 +2916,11 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, mwl8k_tx_reclaim_handler, (unsigned long)hw); tasklet_disable(&priv->tx_reclaim_task); + /* Config workthread */ + priv->config_wq = create_singlethread_workqueue("mwl8k_config"); + if (priv->config_wq == NULL) + goto err_iounmap; + /* Power management cookie */ priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); if (priv->cookie == NULL) @@ -3462,12 +2934,11 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, mutex_init(&priv->fw_mutex); priv->fw_mutex_owner = NULL; priv->fw_mutex_depth = 0; + priv->tx_wait = NULL; priv->hostcmd_wait = NULL; spin_lock_init(&priv->tx_lock); - priv->tx_wait = NULL; - for (i = 0; i < MWL8K_TX_QUEUES; i++) { rc = mwl8k_txq_init(hw, i); if (rc) @@ -3483,7 +2954,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, IRQF_SHARED, MWL8K_NAME, hw); if (rc) { printk(KERN_ERR "%s: failed to register IRQ handler\n", - wiphy_name(hw->wiphy)); + priv->name); goto err_free_queues; } @@ -3491,18 +2962,16 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, mwl8k_hw_reset(priv); /* Ask userland hotplug daemon for the device firmware */ - rc = mwl8k_request_firmware(priv); + rc = mwl8k_request_firmware(priv, (u32)id->driver_data); if (rc) { - printk(KERN_ERR "%s: Firmware files not found\n", - wiphy_name(hw->wiphy)); + printk(KERN_ERR "%s: Firmware files not found\n", priv->name); goto err_free_irq; } /* Load firmware into hardware */ - rc = mwl8k_load_firmware(hw); + rc = mwl8k_load_firmware(priv); if (rc) { - printk(KERN_ERR "%s: Cannot start firmware\n", - wiphy_name(hw->wiphy)); + printk(KERN_ERR "%s: Cannot start firmware\n", priv->name); goto err_stop_firmware; } @@ -3517,31 +2986,16 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); /* Get config data, mac addrs etc */ - if (priv->ap_fw) { - rc = mwl8k_cmd_get_hw_spec_ap(hw); - if (!rc) - rc = mwl8k_cmd_set_hw_spec(hw); - } else { - rc = mwl8k_cmd_get_hw_spec_sta(hw); - } + rc = mwl8k_cmd_get_hw_spec(hw); if (rc) { - printk(KERN_ERR "%s: Cannot initialise firmware\n", - wiphy_name(hw->wiphy)); + printk(KERN_ERR "%s: Cannot initialise firmware\n", priv->name); goto err_stop_firmware; } /* Turn radio off */ rc = mwl8k_cmd_802_11_radio_disable(hw); if (rc) { - printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy)); - goto err_stop_firmware; - } - - /* Clear MAC address */ - rc = mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); - if (rc) { - printk(KERN_ERR "%s: Cannot clear MAC address\n", - wiphy_name(hw->wiphy)); + printk(KERN_ERR "%s: Cannot disable\n", priv->name); goto err_stop_firmware; } @@ -3551,15 +3005,13 @@ 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)); + printk(KERN_ERR "%s: Cannot register device\n", priv->name); goto err_stop_firmware; } - 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", + printk(KERN_INFO "%s: 88w%u v%d, %pM, firmware version %u.%u.%u.%u\n", + wiphy_name(hw->wiphy), priv->part_num, priv->hw_rev, + hw->wiphy->perm_addr, (priv->fw_rev >> 24) & 0xff, (priv->fw_rev >> 16) & 0xff, (priv->fw_rev >> 8) & 0xff, priv->fw_rev & 0xff); @@ -3586,8 +3038,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, if (priv->regs != NULL) pci_iounmap(pdev, priv->regs); - if (priv->sram != NULL) - pci_iounmap(pdev, priv->sram); + if (priv->config_wq != NULL) + destroy_workqueue(priv->config_wq); pci_set_drvdata(pdev, NULL); ieee80211_free_hw(hw); @@ -3621,6 +3073,9 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) /* Remove tx reclaim tasklet */ tasklet_kill(&priv->tx_reclaim_task); + /* Stop config thread */ + destroy_workqueue(priv->config_wq); + /* Stop hardware */ mwl8k_hw_reset(priv); @@ -3633,10 +3088,10 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) mwl8k_rxq_deinit(hw, 0); - pci_free_consistent(priv->pdev, 4, priv->cookie, priv->cookie_dma); + pci_free_consistent(priv->pdev, 4, + priv->cookie, priv->cookie_dma); pci_iounmap(pdev, priv->regs); - pci_iounmap(pdev, priv->sram); pci_set_drvdata(pdev, NULL); ieee80211_free_hw(hw); pci_release_regions(pdev); @@ -3645,7 +3100,7 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) static struct pci_driver mwl8k_driver = { .name = MWL8K_NAME, - .id_table = mwl8k_pci_id_table, + .id_table = mwl8k_table, .probe = mwl8k_probe, .remove = __devexit_p(mwl8k_remove), .shutdown = __devexit_p(mwl8k_shutdown), @@ -3663,8 +3118,3 @@ static void __exit mwl8k_exit(void) module_init(mwl8k_init); module_exit(mwl8k_exit); - -MODULE_DESCRIPTION(MWL8K_DESC); -MODULE_VERSION(MWL8K_VERSION); -MODULE_AUTHOR("Lennert Buytenhek "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/staging/netwave/netwave_cs.c b/trunk/drivers/net/wireless/netwave_cs.c similarity index 100% rename from trunk/drivers/staging/netwave/netwave_cs.c rename to trunk/drivers/net/wireless/netwave_cs.c diff --git a/trunk/drivers/net/wireless/orinoco/Kconfig b/trunk/drivers/net/wireless/orinoco/Kconfig index e2a2c18920aa..dce652054afd 100644 --- a/trunk/drivers/net/wireless/orinoco/Kconfig +++ b/trunk/drivers/net/wireless/orinoco/Kconfig @@ -1,6 +1,6 @@ config HERMES tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)" - depends on (PPC_PMAC || PCI || PCMCIA) + depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211 depends on CFG80211 && CFG80211_WEXT select WIRELESS_EXT select WEXT_SPY diff --git a/trunk/drivers/net/wireless/p54/Kconfig b/trunk/drivers/net/wireless/p54/Kconfig index b0342a520bf1..b45d6a4ed1e8 100644 --- a/trunk/drivers/net/wireless/p54/Kconfig +++ b/trunk/drivers/net/wireless/p54/Kconfig @@ -1,6 +1,6 @@ config P54_COMMON tristate "Softmac Prism54 support" - depends on MAC80211 && EXPERIMENTAL + depends on MAC80211 && WLAN_80211 && EXPERIMENTAL select FW_LOADER ---help--- This is common code for isl38xx/stlc45xx based modules. diff --git a/trunk/drivers/net/wireless/p54/eeprom.c b/trunk/drivers/net/wireless/p54/eeprom.c index 8e3818f6832e..0efe67deedee 100644 --- a/trunk/drivers/net/wireless/p54/eeprom.c +++ b/trunk/drivers/net/wireless/p54/eeprom.c @@ -126,7 +126,7 @@ static int p54_generate_band(struct ieee80211_hw *dev, int ret = -ENOMEM; if ((!list->entries) || (!list->band_channel_num[band])) - return -EINVAL; + return 0; tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); if (!tmp) @@ -158,7 +158,6 @@ static int p54_generate_band(struct ieee80211_hw *dev, (list->channels[i].data & CHAN_HAS_CURVE ? "" : " [curve data]"), list->channels[i].index, list->channels[i].freq); - continue; } tmp->channels[j].band = list->channels[i].band; @@ -166,16 +165,7 @@ static int p54_generate_band(struct ieee80211_hw *dev, j++; } - 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"); - - ret = -ENODATA; - goto err_out; - } - - tmp->n_channels = j; + tmp->n_channels = list->band_channel_num[band]; old = priv->band_table[band]; priv->band_table[band] = tmp; if (old) { @@ -238,13 +228,13 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) struct p54_common *priv = dev->priv; struct p54_channel_list *list; unsigned int i, j, max_channel_num; - int ret = 0; + int ret = -ENOMEM; u16 freq; 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", + printk(KERN_ERR "%s: EEPROM is damaged... you may not be able" + "to use all channels with this device.\n", wiphy_name(dev->wiphy)); max_channel_num = max_t(unsigned int, priv->output_limit->entries, @@ -253,10 +243,8 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) priv->curve_data->entries); list = kzalloc(sizeof(*list), GFP_KERNEL); - if (!list) { - ret = -ENOMEM; + if (!list) goto free; - } list->max_entries = max_channel_num; list->channels = kzalloc(sizeof(struct p54_channel_entry) * @@ -294,8 +282,13 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) p54_compare_channels, NULL); for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) { - if (p54_generate_band(dev, list, i) == 0) + if (list->band_channel_num[i]) { + ret = p54_generate_band(dev, list, i); + if (ret) + goto free; + j++; + } } if (j == 0) { /* no useable band available. */ diff --git a/trunk/drivers/net/wireless/rt2x00/Kconfig b/trunk/drivers/net/wireless/rt2x00/Kconfig index bf60689aaabb..390c0c7b3ac2 100644 --- a/trunk/drivers/net/wireless/rt2x00/Kconfig +++ b/trunk/drivers/net/wireless/rt2x00/Kconfig @@ -1,6 +1,6 @@ menuconfig RT2X00 tristate "Ralink driver support" - depends on MAC80211 + depends on MAC80211 && WLAN_80211 ---help--- This will enable the support for the Ralink drivers, developed in the rt2x00 project . @@ -64,9 +64,8 @@ config RT2800PCI_SOC default y config RT2800PCI - tristate "Ralink rt2800 (PCI/PCMCIA) support (VERY EXPERIMENTAL)" + tristate "Ralink rt2800 (PCI/PCMCIA) support" depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL - select RT2800_LIB select RT2X00_LIB_PCI if RT2800PCI_PCI select RT2X00_LIB_SOC if RT2800PCI_SOC select RT2X00_LIB_HT @@ -78,9 +77,6 @@ config RT2800PCI This adds support for rt2800 wireless chipset family. Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052 - This driver is non-functional at the moment and is intended for - developers. - When compiled as a module, this driver will be called "rt2800pci.ko". config RT2500USB @@ -108,9 +104,8 @@ config RT73USB When compiled as a module, this driver will be called rt73usb. config RT2800USB - tristate "Ralink rt2800 (USB) support (EXPERIMENTAL)" + tristate "Ralink rt2800 (USB) support" depends on USB && EXPERIMENTAL - select RT2800_LIB select RT2X00_LIB_USB select RT2X00_LIB_HT select RT2X00_LIB_FIRMWARE @@ -120,15 +115,8 @@ config RT2800USB This adds experimental support for rt2800 wireless chipset family. Supported chips: RT2770, RT2870 & RT3070. - Known issues: - - support for RT2870 chips doesn't work with 802.11n APs yet - - support for RT3070 chips is non-functional at the moment - When compiled as a module, this driver will be called "rt2800usb.ko". -config RT2800_LIB - tristate - config RT2X00_LIB_PCI tristate select RT2X00_LIB diff --git a/trunk/drivers/net/wireless/rt2x00/Makefile b/trunk/drivers/net/wireless/rt2x00/Makefile index 971339858297..912f5f67e159 100644 --- a/trunk/drivers/net/wireless/rt2x00/Makefile +++ b/trunk/drivers/net/wireless/rt2x00/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o -obj-$(CONFIG_RT2800_LIB) += rt2800lib.o obj-$(CONFIG_RT2400PCI) += rt2400pci.o obj-$(CONFIG_RT2500PCI) += rt2500pci.o obj-$(CONFIG_RT61PCI) += rt61pci.o diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800.h b/trunk/drivers/net/wireless/rt2x00/rt2800.h deleted file mode 100644 index d9b6a72e6d27..000000000000 --- a/trunk/drivers/net/wireless/rt2x00/rt2800.h +++ /dev/null @@ -1,1816 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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. - */ - -/* - Module: rt2800 - Abstract: Data structures and registers for the rt2800 modules. - Supported chipsets: RT2800E, RT2800ED & RT2800U. - */ - -#ifndef RT2800_H -#define RT2800_H - -/* - * RF chip defines. - * - * RF2820 2.4G 2T3R - * RF2850 2.4G/5G 2T3R - * RF2720 2.4G 1T2R - * RF2750 2.4G/5G 1T2R - * RF3020 2.4G 1T1R - * RF2020 2.4G B/G - * RF3021 2.4G 1T2R - * RF3022 2.4G 2T2R - * RF3052 2.4G 2T2R - */ -#define RF2820 0x0001 -#define RF2850 0x0002 -#define RF2720 0x0003 -#define RF2750 0x0004 -#define RF3020 0x0005 -#define RF2020 0x0006 -#define RF3021 0x0007 -#define RF3022 0x0008 -#define RF3052 0x0009 - -/* - * Chipset version. - */ -#define RT2860C_VERSION 0x28600100 -#define RT2860D_VERSION 0x28600101 -#define RT2880E_VERSION 0x28720200 -#define RT2883_VERSION 0x28830300 -#define RT3070_VERSION 0x30700200 - -/* - * Signal information. - * Default offset is required for RSSI <-> dBm conversion. - */ -#define DEFAULT_RSSI_OFFSET 120 /* FIXME */ - -/* - * Register layout information. - */ -#define CSR_REG_BASE 0x1000 -#define CSR_REG_SIZE 0x0800 -#define EEPROM_BASE 0x0000 -#define EEPROM_SIZE 0x0110 -#define BBP_BASE 0x0000 -#define BBP_SIZE 0x0080 -#define RF_BASE 0x0004 -#define RF_SIZE 0x0010 - -/* - * Number of TX queues. - */ -#define NUM_TX_QUEUES 4 - -/* - * USB registers. - */ - -/* - * INT_SOURCE_CSR: Interrupt source register. - * Write one to clear corresponding bit. - * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c - */ -#define INT_SOURCE_CSR 0x0200 -#define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001) -#define INT_SOURCE_CSR_TXDELAYINT FIELD32(0x00000002) -#define INT_SOURCE_CSR_RX_DONE FIELD32(0x00000004) -#define INT_SOURCE_CSR_AC0_DMA_DONE FIELD32(0x00000008) -#define INT_SOURCE_CSR_AC1_DMA_DONE FIELD32(0x00000010) -#define INT_SOURCE_CSR_AC2_DMA_DONE FIELD32(0x00000020) -#define INT_SOURCE_CSR_AC3_DMA_DONE FIELD32(0x00000040) -#define INT_SOURCE_CSR_HCCA_DMA_DONE FIELD32(0x00000080) -#define INT_SOURCE_CSR_MGMT_DMA_DONE FIELD32(0x00000100) -#define INT_SOURCE_CSR_MCU_COMMAND FIELD32(0x00000200) -#define INT_SOURCE_CSR_RXTX_COHERENT FIELD32(0x00000400) -#define INT_SOURCE_CSR_TBTT FIELD32(0x00000800) -#define INT_SOURCE_CSR_PRE_TBTT FIELD32(0x00001000) -#define INT_SOURCE_CSR_TX_FIFO_STATUS FIELD32(0x00002000) -#define INT_SOURCE_CSR_AUTO_WAKEUP FIELD32(0x00004000) -#define INT_SOURCE_CSR_GPTIMER FIELD32(0x00008000) -#define INT_SOURCE_CSR_RX_COHERENT FIELD32(0x00010000) -#define INT_SOURCE_CSR_TX_COHERENT FIELD32(0x00020000) - -/* - * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF. - */ -#define INT_MASK_CSR 0x0204 -#define INT_MASK_CSR_RXDELAYINT FIELD32(0x00000001) -#define INT_MASK_CSR_TXDELAYINT FIELD32(0x00000002) -#define INT_MASK_CSR_RX_DONE FIELD32(0x00000004) -#define INT_MASK_CSR_AC0_DMA_DONE FIELD32(0x00000008) -#define INT_MASK_CSR_AC1_DMA_DONE FIELD32(0x00000010) -#define INT_MASK_CSR_AC2_DMA_DONE FIELD32(0x00000020) -#define INT_MASK_CSR_AC3_DMA_DONE FIELD32(0x00000040) -#define INT_MASK_CSR_HCCA_DMA_DONE FIELD32(0x00000080) -#define INT_MASK_CSR_MGMT_DMA_DONE FIELD32(0x00000100) -#define INT_MASK_CSR_MCU_COMMAND FIELD32(0x00000200) -#define INT_MASK_CSR_RXTX_COHERENT FIELD32(0x00000400) -#define INT_MASK_CSR_TBTT FIELD32(0x00000800) -#define INT_MASK_CSR_PRE_TBTT FIELD32(0x00001000) -#define INT_MASK_CSR_TX_FIFO_STATUS FIELD32(0x00002000) -#define INT_MASK_CSR_AUTO_WAKEUP FIELD32(0x00004000) -#define INT_MASK_CSR_GPTIMER FIELD32(0x00008000) -#define INT_MASK_CSR_RX_COHERENT FIELD32(0x00010000) -#define INT_MASK_CSR_TX_COHERENT FIELD32(0x00020000) - -/* - * WPDMA_GLO_CFG - */ -#define WPDMA_GLO_CFG 0x0208 -#define WPDMA_GLO_CFG_ENABLE_TX_DMA FIELD32(0x00000001) -#define WPDMA_GLO_CFG_TX_DMA_BUSY FIELD32(0x00000002) -#define WPDMA_GLO_CFG_ENABLE_RX_DMA FIELD32(0x00000004) -#define WPDMA_GLO_CFG_RX_DMA_BUSY FIELD32(0x00000008) -#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE FIELD32(0x00000030) -#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE FIELD32(0x00000040) -#define WPDMA_GLO_CFG_BIG_ENDIAN FIELD32(0x00000080) -#define WPDMA_GLO_CFG_RX_HDR_SCATTER FIELD32(0x0000ff00) -#define WPDMA_GLO_CFG_HDR_SEG_LEN FIELD32(0xffff0000) - -/* - * WPDMA_RST_IDX - */ -#define WPDMA_RST_IDX 0x020c -#define WPDMA_RST_IDX_DTX_IDX0 FIELD32(0x00000001) -#define WPDMA_RST_IDX_DTX_IDX1 FIELD32(0x00000002) -#define WPDMA_RST_IDX_DTX_IDX2 FIELD32(0x00000004) -#define WPDMA_RST_IDX_DTX_IDX3 FIELD32(0x00000008) -#define WPDMA_RST_IDX_DTX_IDX4 FIELD32(0x00000010) -#define WPDMA_RST_IDX_DTX_IDX5 FIELD32(0x00000020) -#define WPDMA_RST_IDX_DRX_IDX0 FIELD32(0x00010000) - -/* - * DELAY_INT_CFG - */ -#define DELAY_INT_CFG 0x0210 -#define DELAY_INT_CFG_RXMAX_PTIME FIELD32(0x000000ff) -#define DELAY_INT_CFG_RXMAX_PINT FIELD32(0x00007f00) -#define DELAY_INT_CFG_RXDLY_INT_EN FIELD32(0x00008000) -#define DELAY_INT_CFG_TXMAX_PTIME FIELD32(0x00ff0000) -#define DELAY_INT_CFG_TXMAX_PINT FIELD32(0x7f000000) -#define DELAY_INT_CFG_TXDLY_INT_EN FIELD32(0x80000000) - -/* - * WMM_AIFSN_CFG: Aifsn for each EDCA AC - * AIFSN0: AC_BE - * AIFSN1: AC_BK - * AIFSN2: AC_VI - * AIFSN3: AC_VO - */ -#define WMM_AIFSN_CFG 0x0214 -#define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f) -#define WMM_AIFSN_CFG_AIFSN1 FIELD32(0x000000f0) -#define WMM_AIFSN_CFG_AIFSN2 FIELD32(0x00000f00) -#define WMM_AIFSN_CFG_AIFSN3 FIELD32(0x0000f000) - -/* - * WMM_CWMIN_CSR: CWmin for each EDCA AC - * CWMIN0: AC_BE - * CWMIN1: AC_BK - * CWMIN2: AC_VI - * CWMIN3: AC_VO - */ -#define WMM_CWMIN_CFG 0x0218 -#define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f) -#define WMM_CWMIN_CFG_CWMIN1 FIELD32(0x000000f0) -#define WMM_CWMIN_CFG_CWMIN2 FIELD32(0x00000f00) -#define WMM_CWMIN_CFG_CWMIN3 FIELD32(0x0000f000) - -/* - * WMM_CWMAX_CSR: CWmax for each EDCA AC - * CWMAX0: AC_BE - * CWMAX1: AC_BK - * CWMAX2: AC_VI - * CWMAX3: AC_VO - */ -#define WMM_CWMAX_CFG 0x021c -#define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f) -#define WMM_CWMAX_CFG_CWMAX1 FIELD32(0x000000f0) -#define WMM_CWMAX_CFG_CWMAX2 FIELD32(0x00000f00) -#define WMM_CWMAX_CFG_CWMAX3 FIELD32(0x0000f000) - -/* - * AC_TXOP0: AC_BK/AC_BE TXOP register - * AC0TXOP: AC_BK in unit of 32us - * AC1TXOP: AC_BE in unit of 32us - */ -#define WMM_TXOP0_CFG 0x0220 -#define WMM_TXOP0_CFG_AC0TXOP FIELD32(0x0000ffff) -#define WMM_TXOP0_CFG_AC1TXOP FIELD32(0xffff0000) - -/* - * AC_TXOP1: AC_VO/AC_VI TXOP register - * AC2TXOP: AC_VI in unit of 32us - * AC3TXOP: AC_VO in unit of 32us - */ -#define WMM_TXOP1_CFG 0x0224 -#define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff) -#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000) - -/* - * GPIO_CTRL_CFG: - */ -#define GPIO_CTRL_CFG 0x0228 -#define GPIO_CTRL_CFG_BIT0 FIELD32(0x00000001) -#define GPIO_CTRL_CFG_BIT1 FIELD32(0x00000002) -#define GPIO_CTRL_CFG_BIT2 FIELD32(0x00000004) -#define GPIO_CTRL_CFG_BIT3 FIELD32(0x00000008) -#define GPIO_CTRL_CFG_BIT4 FIELD32(0x00000010) -#define GPIO_CTRL_CFG_BIT5 FIELD32(0x00000020) -#define GPIO_CTRL_CFG_BIT6 FIELD32(0x00000040) -#define GPIO_CTRL_CFG_BIT7 FIELD32(0x00000080) -#define GPIO_CTRL_CFG_BIT8 FIELD32(0x00000100) - -/* - * MCU_CMD_CFG - */ -#define MCU_CMD_CFG 0x022c - -/* - * AC_BK register offsets - */ -#define TX_BASE_PTR0 0x0230 -#define TX_MAX_CNT0 0x0234 -#define TX_CTX_IDX0 0x0238 -#define TX_DTX_IDX0 0x023c - -/* - * AC_BE register offsets - */ -#define TX_BASE_PTR1 0x0240 -#define TX_MAX_CNT1 0x0244 -#define TX_CTX_IDX1 0x0248 -#define TX_DTX_IDX1 0x024c - -/* - * AC_VI register offsets - */ -#define TX_BASE_PTR2 0x0250 -#define TX_MAX_CNT2 0x0254 -#define TX_CTX_IDX2 0x0258 -#define TX_DTX_IDX2 0x025c - -/* - * AC_VO register offsets - */ -#define TX_BASE_PTR3 0x0260 -#define TX_MAX_CNT3 0x0264 -#define TX_CTX_IDX3 0x0268 -#define TX_DTX_IDX3 0x026c - -/* - * HCCA register offsets - */ -#define TX_BASE_PTR4 0x0270 -#define TX_MAX_CNT4 0x0274 -#define TX_CTX_IDX4 0x0278 -#define TX_DTX_IDX4 0x027c - -/* - * MGMT register offsets - */ -#define TX_BASE_PTR5 0x0280 -#define TX_MAX_CNT5 0x0284 -#define TX_CTX_IDX5 0x0288 -#define TX_DTX_IDX5 0x028c - -/* - * RX register offsets - */ -#define RX_BASE_PTR 0x0290 -#define RX_MAX_CNT 0x0294 -#define RX_CRX_IDX 0x0298 -#define RX_DRX_IDX 0x029c - -/* - * PBF_SYS_CTRL - * HOST_RAM_WRITE: enable Host program ram write selection - */ -#define PBF_SYS_CTRL 0x0400 -#define PBF_SYS_CTRL_READY FIELD32(0x00000080) -#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) - -/* - * HOST-MCU shared memory - */ -#define HOST_CMD_CSR 0x0404 -#define HOST_CMD_CSR_HOST_COMMAND FIELD32(0x000000ff) - -/* - * PBF registers - * Most are for debug. Driver doesn't touch PBF register. - */ -#define PBF_CFG 0x0408 -#define PBF_MAX_PCNT 0x040c -#define PBF_CTRL 0x0410 -#define PBF_INT_STA 0x0414 -#define PBF_INT_ENA 0x0418 - -/* - * BCN_OFFSET0: - */ -#define BCN_OFFSET0 0x042c -#define BCN_OFFSET0_BCN0 FIELD32(0x000000ff) -#define BCN_OFFSET0_BCN1 FIELD32(0x0000ff00) -#define BCN_OFFSET0_BCN2 FIELD32(0x00ff0000) -#define BCN_OFFSET0_BCN3 FIELD32(0xff000000) - -/* - * BCN_OFFSET1: - */ -#define BCN_OFFSET1 0x0430 -#define BCN_OFFSET1_BCN4 FIELD32(0x000000ff) -#define BCN_OFFSET1_BCN5 FIELD32(0x0000ff00) -#define BCN_OFFSET1_BCN6 FIELD32(0x00ff0000) -#define BCN_OFFSET1_BCN7 FIELD32(0xff000000) - -/* - * PBF registers - * Most are for debug. Driver doesn't touch PBF register. - */ -#define TXRXQ_PCNT 0x0438 -#define PBF_DBG 0x043c - -/* - * RF registers - */ -#define RF_CSR_CFG 0x0500 -#define RF_CSR_CFG_DATA FIELD32(0x000000ff) -#define RF_CSR_CFG_REGNUM FIELD32(0x00001f00) -#define RF_CSR_CFG_WRITE FIELD32(0x00010000) -#define RF_CSR_CFG_BUSY FIELD32(0x00020000) - -/* - * MAC Control/Status Registers(CSR). - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * MAC_CSR0: ASIC revision number. - * ASIC_REV: 0 - * ASIC_VER: 2860 or 2870 - */ -#define MAC_CSR0 0x1000 -#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff) -#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000) - -/* - * MAC_SYS_CTRL: - */ -#define MAC_SYS_CTRL 0x1004 -#define MAC_SYS_CTRL_RESET_CSR FIELD32(0x00000001) -#define MAC_SYS_CTRL_RESET_BBP FIELD32(0x00000002) -#define MAC_SYS_CTRL_ENABLE_TX FIELD32(0x00000004) -#define MAC_SYS_CTRL_ENABLE_RX FIELD32(0x00000008) -#define MAC_SYS_CTRL_CONTINUOUS_TX FIELD32(0x00000010) -#define MAC_SYS_CTRL_LOOPBACK FIELD32(0x00000020) -#define MAC_SYS_CTRL_WLAN_HALT FIELD32(0x00000040) -#define MAC_SYS_CTRL_RX_TIMESTAMP FIELD32(0x00000080) - -/* - * MAC_ADDR_DW0: STA MAC register 0 - */ -#define MAC_ADDR_DW0 0x1008 -#define MAC_ADDR_DW0_BYTE0 FIELD32(0x000000ff) -#define MAC_ADDR_DW0_BYTE1 FIELD32(0x0000ff00) -#define MAC_ADDR_DW0_BYTE2 FIELD32(0x00ff0000) -#define MAC_ADDR_DW0_BYTE3 FIELD32(0xff000000) - -/* - * MAC_ADDR_DW1: STA MAC register 1 - * UNICAST_TO_ME_MASK: - * Used to mask off bits from byte 5 of the MAC address - * to determine the UNICAST_TO_ME bit for RX frames. - * The full mask is complemented by BSS_ID_MASK: - * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK - */ -#define MAC_ADDR_DW1 0x100c -#define MAC_ADDR_DW1_BYTE4 FIELD32(0x000000ff) -#define MAC_ADDR_DW1_BYTE5 FIELD32(0x0000ff00) -#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK FIELD32(0x00ff0000) - -/* - * MAC_BSSID_DW0: BSSID register 0 - */ -#define MAC_BSSID_DW0 0x1010 -#define MAC_BSSID_DW0_BYTE0 FIELD32(0x000000ff) -#define MAC_BSSID_DW0_BYTE1 FIELD32(0x0000ff00) -#define MAC_BSSID_DW0_BYTE2 FIELD32(0x00ff0000) -#define MAC_BSSID_DW0_BYTE3 FIELD32(0xff000000) - -/* - * MAC_BSSID_DW1: BSSID register 1 - * BSS_ID_MASK: - * 0: 1-BSSID mode (BSS index = 0) - * 1: 2-BSSID mode (BSS index: Byte5, bit 0) - * 2: 4-BSSID mode (BSS index: byte5, bit 0 - 1) - * 3: 8-BSSID mode (BSS index: byte5, bit 0 - 2) - * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the - * BSSID. This will make sure that those bits will be ignored - * when determining the MY_BSS of RX frames. - */ -#define MAC_BSSID_DW1 0x1014 -#define MAC_BSSID_DW1_BYTE4 FIELD32(0x000000ff) -#define MAC_BSSID_DW1_BYTE5 FIELD32(0x0000ff00) -#define MAC_BSSID_DW1_BSS_ID_MASK FIELD32(0x00030000) -#define MAC_BSSID_DW1_BSS_BCN_NUM FIELD32(0x001c0000) - -/* - * MAX_LEN_CFG: Maximum frame length register. - * MAX_MPDU: rt2860b max 16k bytes - * MAX_PSDU: Maximum PSDU length - * (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 - */ -#define MAX_LEN_CFG 0x1018 -#define MAX_LEN_CFG_MAX_MPDU FIELD32(0x00000fff) -#define MAX_LEN_CFG_MAX_PSDU FIELD32(0x00003000) -#define MAX_LEN_CFG_MIN_PSDU FIELD32(0x0000c000) -#define MAX_LEN_CFG_MIN_MPDU FIELD32(0x000f0000) - -/* - * BBP_CSR_CFG: BBP serial control register - * VALUE: Register value to program into BBP - * REG_NUM: Selected BBP register - * READ_CONTROL: 0 write BBP, 1 read BBP - * BUSY: ASIC is busy executing BBP commands - * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks - * BBP_RW_MODE: 0 serial, 1 paralell - */ -#define BBP_CSR_CFG 0x101c -#define BBP_CSR_CFG_VALUE FIELD32(0x000000ff) -#define BBP_CSR_CFG_REGNUM FIELD32(0x0000ff00) -#define BBP_CSR_CFG_READ_CONTROL FIELD32(0x00010000) -#define BBP_CSR_CFG_BUSY FIELD32(0x00020000) -#define BBP_CSR_CFG_BBP_PAR_DUR FIELD32(0x00040000) -#define BBP_CSR_CFG_BBP_RW_MODE FIELD32(0x00080000) - -/* - * RF_CSR_CFG0: RF control register - * REGID_AND_VALUE: Register value to program into RF - * BITWIDTH: Selected RF register - * STANDBYMODE: 0 high when standby, 1 low when standby - * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate - * BUSY: ASIC is busy executing RF commands - */ -#define RF_CSR_CFG0 0x1020 -#define RF_CSR_CFG0_REGID_AND_VALUE FIELD32(0x00ffffff) -#define RF_CSR_CFG0_BITWIDTH FIELD32(0x1f000000) -#define RF_CSR_CFG0_REG_VALUE_BW FIELD32(0x1fffffff) -#define RF_CSR_CFG0_STANDBYMODE FIELD32(0x20000000) -#define RF_CSR_CFG0_SEL FIELD32(0x40000000) -#define RF_CSR_CFG0_BUSY FIELD32(0x80000000) - -/* - * RF_CSR_CFG1: RF control register - * REGID_AND_VALUE: Register value to program into RF - * RFGAP: Gap between BB_CONTROL_RF and RF_LE - * 0: 3 system clock cycle (37.5usec) - * 1: 5 system clock cycle (62.5usec) - */ -#define RF_CSR_CFG1 0x1024 -#define RF_CSR_CFG1_REGID_AND_VALUE FIELD32(0x00ffffff) -#define RF_CSR_CFG1_RFGAP FIELD32(0x1f000000) - -/* - * RF_CSR_CFG2: RF control register - * VALUE: Register value to program into RF - */ -#define RF_CSR_CFG2 0x1028 -#define RF_CSR_CFG2_VALUE FIELD32(0x00ffffff) - -/* - * LED_CFG: LED control - * color LED's: - * 0: off - * 1: blinking upon TX2 - * 2: periodic slow blinking - * 3: always on - * LED polarity: - * 0: active low - * 1: active high - */ -#define LED_CFG 0x102c -#define LED_CFG_ON_PERIOD FIELD32(0x000000ff) -#define LED_CFG_OFF_PERIOD FIELD32(0x0000ff00) -#define LED_CFG_SLOW_BLINK_PERIOD FIELD32(0x003f0000) -#define LED_CFG_R_LED_MODE FIELD32(0x03000000) -#define LED_CFG_G_LED_MODE FIELD32(0x0c000000) -#define LED_CFG_Y_LED_MODE FIELD32(0x30000000) -#define LED_CFG_LED_POLAR FIELD32(0x40000000) - -/* - * XIFS_TIME_CFG: MAC timing - * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX - * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX - * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX - * when MAC doesn't reference BBP signal BBRXEND - * EIFS: unit 1us - * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer - * - */ -#define XIFS_TIME_CFG 0x1100 -#define XIFS_TIME_CFG_CCKM_SIFS_TIME FIELD32(0x000000ff) -#define XIFS_TIME_CFG_OFDM_SIFS_TIME FIELD32(0x0000ff00) -#define XIFS_TIME_CFG_OFDM_XIFS_TIME FIELD32(0x000f0000) -#define XIFS_TIME_CFG_EIFS FIELD32(0x1ff00000) -#define XIFS_TIME_CFG_BB_RXEND_ENABLE FIELD32(0x20000000) - -/* - * BKOFF_SLOT_CFG: - */ -#define BKOFF_SLOT_CFG 0x1104 -#define BKOFF_SLOT_CFG_SLOT_TIME FIELD32(0x000000ff) -#define BKOFF_SLOT_CFG_CC_DELAY_TIME FIELD32(0x0000ff00) - -/* - * NAV_TIME_CFG: - */ -#define NAV_TIME_CFG 0x1108 -#define NAV_TIME_CFG_SIFS FIELD32(0x000000ff) -#define NAV_TIME_CFG_SLOT_TIME FIELD32(0x0000ff00) -#define NAV_TIME_CFG_EIFS FIELD32(0x01ff0000) -#define NAV_TIME_ZERO_SIFS FIELD32(0x02000000) - -/* - * CH_TIME_CFG: count as channel busy - */ -#define CH_TIME_CFG 0x110c - -/* - * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us - */ -#define PBF_LIFE_TIMER 0x1110 - -/* - * BCN_TIME_CFG: - * BEACON_INTERVAL: in unit of 1/16 TU - * TSF_TICKING: Enable TSF auto counting - * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode - * BEACON_GEN: Enable beacon generator - */ -#define BCN_TIME_CFG 0x1114 -#define BCN_TIME_CFG_BEACON_INTERVAL FIELD32(0x0000ffff) -#define BCN_TIME_CFG_TSF_TICKING FIELD32(0x00010000) -#define BCN_TIME_CFG_TSF_SYNC FIELD32(0x00060000) -#define BCN_TIME_CFG_TBTT_ENABLE FIELD32(0x00080000) -#define BCN_TIME_CFG_BEACON_GEN FIELD32(0x00100000) -#define BCN_TIME_CFG_TX_TIME_COMPENSATE FIELD32(0xf0000000) - -/* - * TBTT_SYNC_CFG: - */ -#define TBTT_SYNC_CFG 0x1118 - -/* - * TSF_TIMER_DW0: Local lsb TSF timer, read-only - */ -#define TSF_TIMER_DW0 0x111c -#define TSF_TIMER_DW0_LOW_WORD FIELD32(0xffffffff) - -/* - * TSF_TIMER_DW1: Local msb TSF timer, read-only - */ -#define TSF_TIMER_DW1 0x1120 -#define TSF_TIMER_DW1_HIGH_WORD FIELD32(0xffffffff) - -/* - * TBTT_TIMER: TImer remains till next TBTT, read-only - */ -#define TBTT_TIMER 0x1124 - -/* - * INT_TIMER_CFG: - */ -#define INT_TIMER_CFG 0x1128 - -/* - * INT_TIMER_EN: GP-timer and pre-tbtt Int enable - */ -#define INT_TIMER_EN 0x112c - -/* - * CH_IDLE_STA: channel idle time - */ -#define CH_IDLE_STA 0x1130 - -/* - * CH_BUSY_STA: channel busy time - */ -#define CH_BUSY_STA 0x1134 - -/* - * MAC_STATUS_CFG: - * BBP_RF_BUSY: When set to 0, BBP and RF are stable. - * if 1 or higher one of the 2 registers is busy. - */ -#define MAC_STATUS_CFG 0x1200 -#define MAC_STATUS_CFG_BBP_RF_BUSY FIELD32(0x00000003) - -/* - * PWR_PIN_CFG: - */ -#define PWR_PIN_CFG 0x1204 - -/* - * AUTOWAKEUP_CFG: Manual power control / status register - * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set - * AUTOWAKE: 0:sleep, 1:awake - */ -#define AUTOWAKEUP_CFG 0x1208 -#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME FIELD32(0x000000ff) -#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE FIELD32(0x00007f00) -#define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000) - -/* - * EDCA_AC0_CFG: - */ -#define EDCA_AC0_CFG 0x1300 -#define EDCA_AC0_CFG_TX_OP FIELD32(0x000000ff) -#define EDCA_AC0_CFG_AIFSN FIELD32(0x00000f00) -#define EDCA_AC0_CFG_CWMIN FIELD32(0x0000f000) -#define EDCA_AC0_CFG_CWMAX FIELD32(0x000f0000) - -/* - * EDCA_AC1_CFG: - */ -#define EDCA_AC1_CFG 0x1304 -#define EDCA_AC1_CFG_TX_OP FIELD32(0x000000ff) -#define EDCA_AC1_CFG_AIFSN FIELD32(0x00000f00) -#define EDCA_AC1_CFG_CWMIN FIELD32(0x0000f000) -#define EDCA_AC1_CFG_CWMAX FIELD32(0x000f0000) - -/* - * EDCA_AC2_CFG: - */ -#define EDCA_AC2_CFG 0x1308 -#define EDCA_AC2_CFG_TX_OP FIELD32(0x000000ff) -#define EDCA_AC2_CFG_AIFSN FIELD32(0x00000f00) -#define EDCA_AC2_CFG_CWMIN FIELD32(0x0000f000) -#define EDCA_AC2_CFG_CWMAX FIELD32(0x000f0000) - -/* - * EDCA_AC3_CFG: - */ -#define EDCA_AC3_CFG 0x130c -#define EDCA_AC3_CFG_TX_OP FIELD32(0x000000ff) -#define EDCA_AC3_CFG_AIFSN FIELD32(0x00000f00) -#define EDCA_AC3_CFG_CWMIN FIELD32(0x0000f000) -#define EDCA_AC3_CFG_CWMAX FIELD32(0x000f0000) - -/* - * EDCA_TID_AC_MAP: - */ -#define EDCA_TID_AC_MAP 0x1310 - -/* - * TX_PWR_CFG_0: - */ -#define TX_PWR_CFG_0 0x1314 -#define TX_PWR_CFG_0_1MBS FIELD32(0x0000000f) -#define TX_PWR_CFG_0_2MBS FIELD32(0x000000f0) -#define TX_PWR_CFG_0_55MBS FIELD32(0x00000f00) -#define TX_PWR_CFG_0_11MBS FIELD32(0x0000f000) -#define TX_PWR_CFG_0_6MBS FIELD32(0x000f0000) -#define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000) -#define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000) -#define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000) - -/* - * TX_PWR_CFG_1: - */ -#define TX_PWR_CFG_1 0x1318 -#define TX_PWR_CFG_1_24MBS FIELD32(0x0000000f) -#define TX_PWR_CFG_1_36MBS FIELD32(0x000000f0) -#define TX_PWR_CFG_1_48MBS FIELD32(0x00000f00) -#define TX_PWR_CFG_1_54MBS FIELD32(0x0000f000) -#define TX_PWR_CFG_1_MCS0 FIELD32(0x000f0000) -#define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000) -#define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000) -#define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000) - -/* - * TX_PWR_CFG_2: - */ -#define TX_PWR_CFG_2 0x131c -#define TX_PWR_CFG_2_MCS4 FIELD32(0x0000000f) -#define TX_PWR_CFG_2_MCS5 FIELD32(0x000000f0) -#define TX_PWR_CFG_2_MCS6 FIELD32(0x00000f00) -#define TX_PWR_CFG_2_MCS7 FIELD32(0x0000f000) -#define TX_PWR_CFG_2_MCS8 FIELD32(0x000f0000) -#define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000) -#define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000) -#define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000) - -/* - * TX_PWR_CFG_3: - */ -#define TX_PWR_CFG_3 0x1320 -#define TX_PWR_CFG_3_MCS12 FIELD32(0x0000000f) -#define TX_PWR_CFG_3_MCS13 FIELD32(0x000000f0) -#define TX_PWR_CFG_3_MCS14 FIELD32(0x00000f00) -#define TX_PWR_CFG_3_MCS15 FIELD32(0x0000f000) -#define TX_PWR_CFG_3_UKNOWN1 FIELD32(0x000f0000) -#define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000) -#define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000) -#define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000) - -/* - * TX_PWR_CFG_4: - */ -#define TX_PWR_CFG_4 0x1324 -#define TX_PWR_CFG_4_UKNOWN5 FIELD32(0x0000000f) -#define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0) -#define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00) -#define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000) - -/* - * TX_PIN_CFG: - */ -#define TX_PIN_CFG 0x1328 -#define TX_PIN_CFG_PA_PE_A0_EN FIELD32(0x00000001) -#define TX_PIN_CFG_PA_PE_G0_EN FIELD32(0x00000002) -#define TX_PIN_CFG_PA_PE_A1_EN FIELD32(0x00000004) -#define TX_PIN_CFG_PA_PE_G1_EN FIELD32(0x00000008) -#define TX_PIN_CFG_PA_PE_A0_POL FIELD32(0x00000010) -#define TX_PIN_CFG_PA_PE_G0_POL FIELD32(0x00000020) -#define TX_PIN_CFG_PA_PE_A1_POL FIELD32(0x00000040) -#define TX_PIN_CFG_PA_PE_G1_POL FIELD32(0x00000080) -#define TX_PIN_CFG_LNA_PE_A0_EN FIELD32(0x00000100) -#define TX_PIN_CFG_LNA_PE_G0_EN FIELD32(0x00000200) -#define TX_PIN_CFG_LNA_PE_A1_EN FIELD32(0x00000400) -#define TX_PIN_CFG_LNA_PE_G1_EN FIELD32(0x00000800) -#define TX_PIN_CFG_LNA_PE_A0_POL FIELD32(0x00001000) -#define TX_PIN_CFG_LNA_PE_G0_POL FIELD32(0x00002000) -#define TX_PIN_CFG_LNA_PE_A1_POL FIELD32(0x00004000) -#define TX_PIN_CFG_LNA_PE_G1_POL FIELD32(0x00008000) -#define TX_PIN_CFG_RFTR_EN FIELD32(0x00010000) -#define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000) -#define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000) -#define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000) - -/* - * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz - */ -#define TX_BAND_CFG 0x132c -#define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001) -#define TX_BAND_CFG_A FIELD32(0x00000002) -#define TX_BAND_CFG_BG FIELD32(0x00000004) - -/* - * TX_SW_CFG0: - */ -#define TX_SW_CFG0 0x1330 - -/* - * TX_SW_CFG1: - */ -#define TX_SW_CFG1 0x1334 - -/* - * TX_SW_CFG2: - */ -#define TX_SW_CFG2 0x1338 - -/* - * TXOP_THRES_CFG: - */ -#define TXOP_THRES_CFG 0x133c - -/* - * TXOP_CTRL_CFG: - */ -#define TXOP_CTRL_CFG 0x1340 - -/* - * TX_RTS_CFG: - * RTS_THRES: unit:byte - * RTS_FBK_EN: enable rts rate fallback - */ -#define TX_RTS_CFG 0x1344 -#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT FIELD32(0x000000ff) -#define TX_RTS_CFG_RTS_THRES FIELD32(0x00ffff00) -#define TX_RTS_CFG_RTS_FBK_EN FIELD32(0x01000000) - -/* - * TX_TIMEOUT_CFG: - * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us - * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure - * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation. - * it is recommended that: - * (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) - */ -#define TX_TIMEOUT_CFG 0x1348 -#define TX_TIMEOUT_CFG_MPDU_LIFETIME FIELD32(0x000000f0) -#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT FIELD32(0x0000ff00) -#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT FIELD32(0x00ff0000) - -/* - * TX_RTY_CFG: - * SHORT_RTY_LIMIT: short retry limit - * LONG_RTY_LIMIT: long retry limit - * LONG_RTY_THRE: Long retry threshoold - * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode - * 0:expired by retry limit, 1: expired by mpdu life timer - * AGG_RTY_MODE: Aggregate MPDU retry mode - * 0:expired by retry limit, 1: expired by mpdu life timer - * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable - */ -#define TX_RTY_CFG 0x134c -#define TX_RTY_CFG_SHORT_RTY_LIMIT FIELD32(0x000000ff) -#define TX_RTY_CFG_LONG_RTY_LIMIT FIELD32(0x0000ff00) -#define TX_RTY_CFG_LONG_RTY_THRE FIELD32(0x0fff0000) -#define TX_RTY_CFG_NON_AGG_RTY_MODE FIELD32(0x10000000) -#define TX_RTY_CFG_AGG_RTY_MODE FIELD32(0x20000000) -#define TX_RTY_CFG_TX_AUTO_FB_ENABLE FIELD32(0x40000000) - -/* - * TX_LINK_CFG: - * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us - * MFB_ENABLE: TX apply remote MFB 1:enable - * REMOTE_UMFS_ENABLE: remote unsolicit MFB enable - * 0: not apply remote remote unsolicit (MFS=7) - * TX_MRQ_EN: MCS request TX enable - * TX_RDG_EN: RDG TX enable - * TX_CF_ACK_EN: Piggyback CF-ACK enable - * REMOTE_MFB: remote MCS feedback - * REMOTE_MFS: remote MCS feedback sequence number - */ -#define TX_LINK_CFG 0x1350 -#define TX_LINK_CFG_REMOTE_MFB_LIFETIME FIELD32(0x000000ff) -#define TX_LINK_CFG_MFB_ENABLE FIELD32(0x00000100) -#define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200) -#define TX_LINK_CFG_TX_MRQ_EN FIELD32(0x00000400) -#define TX_LINK_CFG_TX_RDG_EN FIELD32(0x00000800) -#define TX_LINK_CFG_TX_CF_ACK_EN FIELD32(0x00001000) -#define TX_LINK_CFG_REMOTE_MFB FIELD32(0x00ff0000) -#define TX_LINK_CFG_REMOTE_MFS FIELD32(0xff000000) - -/* - * HT_FBK_CFG0: - */ -#define HT_FBK_CFG0 0x1354 -#define HT_FBK_CFG0_HTMCS0FBK FIELD32(0x0000000f) -#define HT_FBK_CFG0_HTMCS1FBK FIELD32(0x000000f0) -#define HT_FBK_CFG0_HTMCS2FBK FIELD32(0x00000f00) -#define HT_FBK_CFG0_HTMCS3FBK FIELD32(0x0000f000) -#define HT_FBK_CFG0_HTMCS4FBK FIELD32(0x000f0000) -#define HT_FBK_CFG0_HTMCS5FBK FIELD32(0x00f00000) -#define HT_FBK_CFG0_HTMCS6FBK FIELD32(0x0f000000) -#define HT_FBK_CFG0_HTMCS7FBK FIELD32(0xf0000000) - -/* - * HT_FBK_CFG1: - */ -#define HT_FBK_CFG1 0x1358 -#define HT_FBK_CFG1_HTMCS8FBK FIELD32(0x0000000f) -#define HT_FBK_CFG1_HTMCS9FBK FIELD32(0x000000f0) -#define HT_FBK_CFG1_HTMCS10FBK FIELD32(0x00000f00) -#define HT_FBK_CFG1_HTMCS11FBK FIELD32(0x0000f000) -#define HT_FBK_CFG1_HTMCS12FBK FIELD32(0x000f0000) -#define HT_FBK_CFG1_HTMCS13FBK FIELD32(0x00f00000) -#define HT_FBK_CFG1_HTMCS14FBK FIELD32(0x0f000000) -#define HT_FBK_CFG1_HTMCS15FBK FIELD32(0xf0000000) - -/* - * LG_FBK_CFG0: - */ -#define LG_FBK_CFG0 0x135c -#define LG_FBK_CFG0_OFDMMCS0FBK FIELD32(0x0000000f) -#define LG_FBK_CFG0_OFDMMCS1FBK FIELD32(0x000000f0) -#define LG_FBK_CFG0_OFDMMCS2FBK FIELD32(0x00000f00) -#define LG_FBK_CFG0_OFDMMCS3FBK FIELD32(0x0000f000) -#define LG_FBK_CFG0_OFDMMCS4FBK FIELD32(0x000f0000) -#define LG_FBK_CFG0_OFDMMCS5FBK FIELD32(0x00f00000) -#define LG_FBK_CFG0_OFDMMCS6FBK FIELD32(0x0f000000) -#define LG_FBK_CFG0_OFDMMCS7FBK FIELD32(0xf0000000) - -/* - * LG_FBK_CFG1: - */ -#define LG_FBK_CFG1 0x1360 -#define LG_FBK_CFG0_CCKMCS0FBK FIELD32(0x0000000f) -#define LG_FBK_CFG0_CCKMCS1FBK FIELD32(0x000000f0) -#define LG_FBK_CFG0_CCKMCS2FBK FIELD32(0x00000f00) -#define LG_FBK_CFG0_CCKMCS3FBK FIELD32(0x0000f000) - -/* - * CCK_PROT_CFG: CCK Protection - * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd) - * PROTECT_CTRL: Protection control frame type for CCK TX - * 0:none, 1:RTS/CTS, 2:CTS-to-self - * PROTECT_NAV: TXOP protection type for CCK TX - * 0:none, 1:ShortNAVprotect, 2:LongNAVProtect - * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow - * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow - * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow - * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow - * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow - * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow - * RTS_TH_EN: RTS threshold enable on CCK TX - */ -#define CCK_PROT_CFG 0x1364 -#define CCK_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) -#define CCK_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) -#define CCK_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) -#define CCK_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) -#define CCK_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) -#define CCK_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) -#define CCK_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) -#define CCK_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) -#define CCK_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) -#define CCK_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) - -/* - * OFDM_PROT_CFG: OFDM Protection - */ -#define OFDM_PROT_CFG 0x1368 -#define OFDM_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) -#define OFDM_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) -#define OFDM_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) -#define OFDM_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) -#define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) -#define OFDM_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) -#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) -#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) -#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) -#define OFDM_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) - -/* - * MM20_PROT_CFG: MM20 Protection - */ -#define MM20_PROT_CFG 0x136c -#define MM20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) -#define MM20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) -#define MM20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) -#define MM20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) -#define MM20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) -#define MM20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) -#define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) -#define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) -#define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) -#define MM20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) - -/* - * MM40_PROT_CFG: MM40 Protection - */ -#define MM40_PROT_CFG 0x1370 -#define MM40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) -#define MM40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) -#define MM40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) -#define MM40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) -#define MM40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) -#define MM40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) -#define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) -#define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) -#define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) -#define MM40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) - -/* - * GF20_PROT_CFG: GF20 Protection - */ -#define GF20_PROT_CFG 0x1374 -#define GF20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) -#define GF20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) -#define GF20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) -#define GF20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) -#define GF20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) -#define GF20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) -#define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) -#define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) -#define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) -#define GF20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) - -/* - * GF40_PROT_CFG: GF40 Protection - */ -#define GF40_PROT_CFG 0x1378 -#define GF40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) -#define GF40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) -#define GF40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) -#define GF40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) -#define GF40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) -#define GF40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) -#define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) -#define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) -#define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) -#define GF40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) - -/* - * EXP_CTS_TIME: - */ -#define EXP_CTS_TIME 0x137c - -/* - * EXP_ACK_TIME: - */ -#define EXP_ACK_TIME 0x1380 - -/* - * RX_FILTER_CFG: RX configuration register. - */ -#define RX_FILTER_CFG 0x1400 -#define RX_FILTER_CFG_DROP_CRC_ERROR FIELD32(0x00000001) -#define RX_FILTER_CFG_DROP_PHY_ERROR FIELD32(0x00000002) -#define RX_FILTER_CFG_DROP_NOT_TO_ME FIELD32(0x00000004) -#define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008) -#define RX_FILTER_CFG_DROP_VER_ERROR FIELD32(0x00000010) -#define RX_FILTER_CFG_DROP_MULTICAST FIELD32(0x00000020) -#define RX_FILTER_CFG_DROP_BROADCAST FIELD32(0x00000040) -#define RX_FILTER_CFG_DROP_DUPLICATE FIELD32(0x00000080) -#define RX_FILTER_CFG_DROP_CF_END_ACK FIELD32(0x00000100) -#define RX_FILTER_CFG_DROP_CF_END FIELD32(0x00000200) -#define RX_FILTER_CFG_DROP_ACK FIELD32(0x00000400) -#define RX_FILTER_CFG_DROP_CTS FIELD32(0x00000800) -#define RX_FILTER_CFG_DROP_RTS FIELD32(0x00001000) -#define RX_FILTER_CFG_DROP_PSPOLL FIELD32(0x00002000) -#define RX_FILTER_CFG_DROP_BA FIELD32(0x00004000) -#define RX_FILTER_CFG_DROP_BAR FIELD32(0x00008000) -#define RX_FILTER_CFG_DROP_CNTL FIELD32(0x00010000) - -/* - * AUTO_RSP_CFG: - * AUTORESPONDER: 0: disable, 1: enable - * BAC_ACK_POLICY: 0:long, 1:short preamble - * CTS_40_MMODE: Response CTS 40MHz duplicate mode - * CTS_40_MREF: Response CTS 40MHz duplicate mode - * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble - * DUAL_CTS_EN: Power bit value in control frame - * ACK_CTS_PSM_BIT:Power bit value in control frame - */ -#define AUTO_RSP_CFG 0x1404 -#define AUTO_RSP_CFG_AUTORESPONDER FIELD32(0x00000001) -#define AUTO_RSP_CFG_BAC_ACK_POLICY FIELD32(0x00000002) -#define AUTO_RSP_CFG_CTS_40_MMODE FIELD32(0x00000004) -#define AUTO_RSP_CFG_CTS_40_MREF FIELD32(0x00000008) -#define AUTO_RSP_CFG_AR_PREAMBLE FIELD32(0x00000010) -#define AUTO_RSP_CFG_DUAL_CTS_EN FIELD32(0x00000040) -#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT FIELD32(0x00000080) - -/* - * LEGACY_BASIC_RATE: - */ -#define LEGACY_BASIC_RATE 0x1408 - -/* - * HT_BASIC_RATE: - */ -#define HT_BASIC_RATE 0x140c - -/* - * HT_CTRL_CFG: - */ -#define HT_CTRL_CFG 0x1410 - -/* - * SIFS_COST_CFG: - */ -#define SIFS_COST_CFG 0x1414 - -/* - * RX_PARSER_CFG: - * Set NAV for all received frames - */ -#define RX_PARSER_CFG 0x1418 - -/* - * TX_SEC_CNT0: - */ -#define TX_SEC_CNT0 0x1500 - -/* - * RX_SEC_CNT0: - */ -#define RX_SEC_CNT0 0x1504 - -/* - * CCMP_FC_MUTE: - */ -#define CCMP_FC_MUTE 0x1508 - -/* - * TXOP_HLDR_ADDR0: - */ -#define TXOP_HLDR_ADDR0 0x1600 - -/* - * TXOP_HLDR_ADDR1: - */ -#define TXOP_HLDR_ADDR1 0x1604 - -/* - * TXOP_HLDR_ET: - */ -#define TXOP_HLDR_ET 0x1608 - -/* - * QOS_CFPOLL_RA_DW0: - */ -#define QOS_CFPOLL_RA_DW0 0x160c - -/* - * QOS_CFPOLL_RA_DW1: - */ -#define QOS_CFPOLL_RA_DW1 0x1610 - -/* - * QOS_CFPOLL_QC: - */ -#define QOS_CFPOLL_QC 0x1614 - -/* - * RX_STA_CNT0: RX PLCP error count & RX CRC error count - */ -#define RX_STA_CNT0 0x1700 -#define RX_STA_CNT0_CRC_ERR FIELD32(0x0000ffff) -#define RX_STA_CNT0_PHY_ERR FIELD32(0xffff0000) - -/* - * RX_STA_CNT1: RX False CCA count & RX LONG frame count - */ -#define RX_STA_CNT1 0x1704 -#define RX_STA_CNT1_FALSE_CCA FIELD32(0x0000ffff) -#define RX_STA_CNT1_PLCP_ERR FIELD32(0xffff0000) - -/* - * RX_STA_CNT2: - */ -#define RX_STA_CNT2 0x1708 -#define RX_STA_CNT2_RX_DUPLI_COUNT FIELD32(0x0000ffff) -#define RX_STA_CNT2_RX_FIFO_OVERFLOW FIELD32(0xffff0000) - -/* - * TX_STA_CNT0: TX Beacon count - */ -#define TX_STA_CNT0 0x170c -#define TX_STA_CNT0_TX_FAIL_COUNT FIELD32(0x0000ffff) -#define TX_STA_CNT0_TX_BEACON_COUNT FIELD32(0xffff0000) - -/* - * TX_STA_CNT1: TX tx count - */ -#define TX_STA_CNT1 0x1710 -#define TX_STA_CNT1_TX_SUCCESS FIELD32(0x0000ffff) -#define TX_STA_CNT1_TX_RETRANSMIT FIELD32(0xffff0000) - -/* - * TX_STA_CNT2: TX tx count - */ -#define TX_STA_CNT2 0x1714 -#define TX_STA_CNT2_TX_ZERO_LEN_COUNT FIELD32(0x0000ffff) -#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) - -/* - * TX_STA_FIFO: TX Result for specific PID status fifo register - */ -#define TX_STA_FIFO 0x1718 -#define TX_STA_FIFO_VALID FIELD32(0x00000001) -#define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e) -#define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020) -#define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040) -#define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080) -#define TX_STA_FIFO_WCID FIELD32(0x0000ff00) -#define TX_STA_FIFO_SUCCESS_RATE FIELD32(0xffff0000) -#define TX_STA_FIFO_MCS FIELD32(0x007f0000) -#define TX_STA_FIFO_PHYMODE FIELD32(0xc0000000) - -/* - * TX_AGG_CNT: Debug counter - */ -#define TX_AGG_CNT 0x171c -#define TX_AGG_CNT_NON_AGG_TX_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT_AGG_TX_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT0: - */ -#define TX_AGG_CNT0 0x1720 -#define TX_AGG_CNT0_AGG_SIZE_1_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT0_AGG_SIZE_2_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT1: - */ -#define TX_AGG_CNT1 0x1724 -#define TX_AGG_CNT1_AGG_SIZE_3_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT1_AGG_SIZE_4_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT2: - */ -#define TX_AGG_CNT2 0x1728 -#define TX_AGG_CNT2_AGG_SIZE_5_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT2_AGG_SIZE_6_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT3: - */ -#define TX_AGG_CNT3 0x172c -#define TX_AGG_CNT3_AGG_SIZE_7_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT3_AGG_SIZE_8_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT4: - */ -#define TX_AGG_CNT4 0x1730 -#define TX_AGG_CNT4_AGG_SIZE_9_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT4_AGG_SIZE_10_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT5: - */ -#define TX_AGG_CNT5 0x1734 -#define TX_AGG_CNT5_AGG_SIZE_11_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT5_AGG_SIZE_12_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT6: - */ -#define TX_AGG_CNT6 0x1738 -#define TX_AGG_CNT6_AGG_SIZE_13_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT6_AGG_SIZE_14_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT7: - */ -#define TX_AGG_CNT7 0x173c -#define TX_AGG_CNT7_AGG_SIZE_15_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT7_AGG_SIZE_16_COUNT FIELD32(0xffff0000) - -/* - * MPDU_DENSITY_CNT: - * TX_ZERO_DEL: TX zero length delimiter count - * RX_ZERO_DEL: RX zero length delimiter count - */ -#define MPDU_DENSITY_CNT 0x1740 -#define MPDU_DENSITY_CNT_TX_ZERO_DEL FIELD32(0x0000ffff) -#define MPDU_DENSITY_CNT_RX_ZERO_DEL FIELD32(0xffff0000) - -/* - * Security key table memory. - * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry - * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry - * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry - * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry - * SHARED_KEY_TABLE_BASE: 32-byte * 16-entry - * SHARED_KEY_MODE_BASE: 4-byte * 16-entry - */ -#define MAC_WCID_BASE 0x1800 -#define PAIRWISE_KEY_TABLE_BASE 0x4000 -#define MAC_IVEIV_TABLE_BASE 0x6000 -#define MAC_WCID_ATTRIBUTE_BASE 0x6800 -#define SHARED_KEY_TABLE_BASE 0x6c00 -#define SHARED_KEY_MODE_BASE 0x7000 - -#define MAC_WCID_ENTRY(__idx) \ - ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) ) -#define PAIRWISE_KEY_ENTRY(__idx) \ - ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) -#define MAC_IVEIV_ENTRY(__idx) \ - ( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) ) -#define MAC_WCID_ATTR_ENTRY(__idx) \ - ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) -#define SHARED_KEY_ENTRY(__idx) \ - ( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) -#define SHARED_KEY_MODE_ENTRY(__idx) \ - ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) ) - -struct mac_wcid_entry { - u8 mac[6]; - u8 reserved[2]; -} __attribute__ ((packed)); - -struct hw_key_entry { - u8 key[16]; - u8 tx_mic[8]; - u8 rx_mic[8]; -} __attribute__ ((packed)); - -struct mac_iveiv_entry { - u8 iv[8]; -} __attribute__ ((packed)); - -/* - * MAC_WCID_ATTRIBUTE: - */ -#define MAC_WCID_ATTRIBUTE_KEYTAB FIELD32(0x00000001) -#define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e) -#define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) -#define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) - -/* - * SHARED_KEY_MODE: - */ -#define SHARED_KEY_MODE_BSS0_KEY0 FIELD32(0x00000007) -#define SHARED_KEY_MODE_BSS0_KEY1 FIELD32(0x00000070) -#define SHARED_KEY_MODE_BSS0_KEY2 FIELD32(0x00000700) -#define SHARED_KEY_MODE_BSS0_KEY3 FIELD32(0x00007000) -#define SHARED_KEY_MODE_BSS1_KEY0 FIELD32(0x00070000) -#define SHARED_KEY_MODE_BSS1_KEY1 FIELD32(0x00700000) -#define SHARED_KEY_MODE_BSS1_KEY2 FIELD32(0x07000000) -#define SHARED_KEY_MODE_BSS1_KEY3 FIELD32(0x70000000) - -/* - * HOST-MCU communication - */ - -/* - * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. - */ -#define H2M_MAILBOX_CSR 0x7010 -#define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff) -#define H2M_MAILBOX_CSR_ARG1 FIELD32(0x0000ff00) -#define H2M_MAILBOX_CSR_CMD_TOKEN FIELD32(0x00ff0000) -#define H2M_MAILBOX_CSR_OWNER FIELD32(0xff000000) - -/* - * H2M_MAILBOX_CID: - */ -#define H2M_MAILBOX_CID 0x7014 -#define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff) -#define H2M_MAILBOX_CID_CMD1 FIELD32(0x0000ff00) -#define H2M_MAILBOX_CID_CMD2 FIELD32(0x00ff0000) -#define H2M_MAILBOX_CID_CMD3 FIELD32(0xff000000) - -/* - * H2M_MAILBOX_STATUS: - */ -#define H2M_MAILBOX_STATUS 0x701c - -/* - * H2M_INT_SRC: - */ -#define H2M_INT_SRC 0x7024 - -/* - * H2M_BBP_AGENT: - */ -#define H2M_BBP_AGENT 0x7028 - -/* - * MCU_LEDCS: LED control for MCU Mailbox. - */ -#define MCU_LEDCS_LED_MODE FIELD8(0x1f) -#define MCU_LEDCS_POLARITY FIELD8(0x01) - -/* - * HW_CS_CTS_BASE: - * Carrier-sense CTS frame base address. - * It's where mac stores carrier-sense frame for carrier-sense function. - */ -#define HW_CS_CTS_BASE 0x7700 - -/* - * HW_DFS_CTS_BASE: - * DFS CTS frame base address. It's where mac stores CTS frame for DFS. - */ -#define HW_DFS_CTS_BASE 0x7780 - -/* - * TXRX control registers - base address 0x3000 - */ - -/* - * TXRX_CSR1: - * rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. - */ -#define TXRX_CSR1 0x77d0 - -/* - * HW_DEBUG_SETTING_BASE: - * since NULL frame won't be that long (256 byte) - * We steal 16 tail bytes to save debugging settings - */ -#define HW_DEBUG_SETTING_BASE 0x77f0 -#define HW_DEBUG_SETTING_BASE2 0x7770 - -/* - * HW_BEACON_BASE - * In order to support maximum 8 MBSS and its maximum length - * is 512 bytes for each beacon - * Three section discontinue memory segments will be used. - * 1. The original region for BCN 0~3 - * 2. Extract memory from FCE table for BCN 4~5 - * 3. Extract memory from Pair-wise key table for BCN 6~7 - * It occupied those memory of wcid 238~253 for BCN 6 - * and wcid 222~237 for BCN 7 - * - * IMPORTANT NOTE: Not sure why legacy driver does this, - * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6. - */ -#define HW_BEACON_BASE0 0x7800 -#define HW_BEACON_BASE1 0x7a00 -#define HW_BEACON_BASE2 0x7c00 -#define HW_BEACON_BASE3 0x7e00 -#define HW_BEACON_BASE4 0x7200 -#define HW_BEACON_BASE5 0x7400 -#define HW_BEACON_BASE6 0x5dc0 -#define HW_BEACON_BASE7 0x5bc0 - -#define HW_BEACON_OFFSET(__index) \ - ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \ - (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \ - (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) ) - -/* - * BBP registers. - * The wordsize of the BBP is 8 bits. - */ - -/* - * BBP 1: TX Antenna - */ -#define BBP1_TX_POWER FIELD8(0x07) -#define BBP1_TX_ANTENNA FIELD8(0x18) - -/* - * BBP 3: RX Antenna - */ -#define BBP3_RX_ANTENNA FIELD8(0x18) -#define BBP3_HT40_PLUS FIELD8(0x20) - -/* - * BBP 4: Bandwidth - */ -#define BBP4_TX_BF FIELD8(0x01) -#define BBP4_BANDWIDTH FIELD8(0x18) - -/* - * RFCSR registers - * The wordsize of the RFCSR is 8 bits. - */ - -/* - * RFCSR 6: - */ -#define RFCSR6_R FIELD8(0x03) - -/* - * RFCSR 7: - */ -#define RFCSR7_RF_TUNING FIELD8(0x01) - -/* - * RFCSR 12: - */ -#define RFCSR12_TX_POWER FIELD8(0x1f) - -/* - * RFCSR 22: - */ -#define RFCSR22_BASEBAND_LOOPBACK FIELD8(0x01) - -/* - * RFCSR 23: - */ -#define RFCSR23_FREQ_OFFSET FIELD8(0x7f) - -/* - * RFCSR 30: - */ -#define RFCSR30_RF_CALIBRATION FIELD8(0x80) - -/* - * RF registers - */ - -/* - * RF 2 - */ -#define RF2_ANTENNA_RX2 FIELD32(0x00000040) -#define RF2_ANTENNA_TX1 FIELD32(0x00004000) -#define RF2_ANTENNA_RX1 FIELD32(0x00020000) - -/* - * RF 3 - */ -#define RF3_TXPOWER_G FIELD32(0x00003e00) -#define RF3_TXPOWER_A_7DBM_BOOST FIELD32(0x00000200) -#define RF3_TXPOWER_A FIELD32(0x00003c00) - -/* - * RF 4 - */ -#define RF4_TXPOWER_G FIELD32(0x000007c0) -#define RF4_TXPOWER_A_7DBM_BOOST FIELD32(0x00000040) -#define RF4_TXPOWER_A FIELD32(0x00000780) -#define RF4_FREQ_OFFSET FIELD32(0x001f8000) -#define RF4_HT40 FIELD32(0x00200000) - -/* - * EEPROM content. - * The wordsize of the EEPROM is 16 bits. - */ - -/* - * EEPROM Version - */ -#define EEPROM_VERSION 0x0001 -#define EEPROM_VERSION_FAE FIELD16(0x00ff) -#define EEPROM_VERSION_VERSION FIELD16(0xff00) - -/* - * HW MAC address. - */ -#define EEPROM_MAC_ADDR_0 0x0002 -#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) -#define EEPROM_MAC_ADDR_1 0x0003 -#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) -#define EEPROM_MAC_ADDR_2 0x0004 -#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) - -/* - * EEPROM ANTENNA config - * RXPATH: 1: 1R, 2: 2R, 3: 3R - * TXPATH: 1: 1T, 2: 2T - */ -#define EEPROM_ANTENNA 0x001a -#define EEPROM_ANTENNA_RXPATH FIELD16(0x000f) -#define EEPROM_ANTENNA_TXPATH FIELD16(0x00f0) -#define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0f00) - -/* - * EEPROM NIC config - * CARDBUS_ACCEL: 0 - enable, 1 - disable - */ -#define EEPROM_NIC 0x001b -#define EEPROM_NIC_HW_RADIO FIELD16(0x0001) -#define EEPROM_NIC_DYNAMIC_TX_AGC FIELD16(0x0002) -#define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0004) -#define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0008) -#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0010) -#define EEPROM_NIC_BW40M_SB_BG FIELD16(0x0020) -#define EEPROM_NIC_BW40M_SB_A FIELD16(0x0040) -#define EEPROM_NIC_WPS_PBC FIELD16(0x0080) -#define EEPROM_NIC_BW40M_BG FIELD16(0x0100) -#define EEPROM_NIC_BW40M_A FIELD16(0x0200) - -/* - * EEPROM frequency - */ -#define EEPROM_FREQ 0x001d -#define EEPROM_FREQ_OFFSET FIELD16(0x00ff) -#define EEPROM_FREQ_LED_MODE FIELD16(0x7f00) -#define EEPROM_FREQ_LED_POLARITY FIELD16(0x1000) - -/* - * EEPROM LED - * POLARITY_RDY_G: Polarity RDY_G setting. - * POLARITY_RDY_A: Polarity RDY_A setting. - * POLARITY_ACT: Polarity ACT setting. - * POLARITY_GPIO_0: Polarity GPIO0 setting. - * POLARITY_GPIO_1: Polarity GPIO1 setting. - * POLARITY_GPIO_2: Polarity GPIO2 setting. - * POLARITY_GPIO_3: Polarity GPIO3 setting. - * POLARITY_GPIO_4: Polarity GPIO4 setting. - * LED_MODE: Led mode. - */ -#define EEPROM_LED1 0x001e -#define EEPROM_LED2 0x001f -#define EEPROM_LED3 0x0020 -#define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001) -#define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002) -#define EEPROM_LED_POLARITY_ACT FIELD16(0x0004) -#define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008) -#define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010) -#define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020) -#define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040) -#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080) -#define EEPROM_LED_LED_MODE FIELD16(0x1f00) - -/* - * EEPROM LNA - */ -#define EEPROM_LNA 0x0022 -#define EEPROM_LNA_BG FIELD16(0x00ff) -#define EEPROM_LNA_A0 FIELD16(0xff00) - -/* - * EEPROM RSSI BG offset - */ -#define EEPROM_RSSI_BG 0x0023 -#define EEPROM_RSSI_BG_OFFSET0 FIELD16(0x00ff) -#define EEPROM_RSSI_BG_OFFSET1 FIELD16(0xff00) - -/* - * EEPROM RSSI BG2 offset - */ -#define EEPROM_RSSI_BG2 0x0024 -#define EEPROM_RSSI_BG2_OFFSET2 FIELD16(0x00ff) -#define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00) - -/* - * EEPROM RSSI A offset - */ -#define EEPROM_RSSI_A 0x0025 -#define EEPROM_RSSI_A_OFFSET0 FIELD16(0x00ff) -#define EEPROM_RSSI_A_OFFSET1 FIELD16(0xff00) - -/* - * EEPROM RSSI A2 offset - */ -#define EEPROM_RSSI_A2 0x0026 -#define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff) -#define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) - -/* - * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power. - * This is delta in 40MHZ. - * VALUE: Tx Power dalta value (MAX=4) - * TYPE: 1: Plus the delta value, 0: minus the delta value - * TXPOWER: Enable: - */ -#define EEPROM_TXPOWER_DELTA 0x0028 -#define EEPROM_TXPOWER_DELTA_VALUE FIELD16(0x003f) -#define EEPROM_TXPOWER_DELTA_TYPE FIELD16(0x0040) -#define EEPROM_TXPOWER_DELTA_TXPOWER FIELD16(0x0080) - -/* - * EEPROM TXPOWER 802.11BG - */ -#define EEPROM_TXPOWER_BG1 0x0029 -#define EEPROM_TXPOWER_BG2 0x0030 -#define EEPROM_TXPOWER_BG_SIZE 7 -#define EEPROM_TXPOWER_BG_1 FIELD16(0x00ff) -#define EEPROM_TXPOWER_BG_2 FIELD16(0xff00) - -/* - * EEPROM TXPOWER 802.11A - */ -#define EEPROM_TXPOWER_A1 0x003c -#define EEPROM_TXPOWER_A2 0x0053 -#define EEPROM_TXPOWER_A_SIZE 6 -#define EEPROM_TXPOWER_A_1 FIELD16(0x00ff) -#define EEPROM_TXPOWER_A_2 FIELD16(0xff00) - -/* - * EEPROM TXpower byrate: 20MHZ power - */ -#define EEPROM_TXPOWER_BYRATE 0x006f - -/* - * EEPROM BBP. - */ -#define EEPROM_BBP_START 0x0078 -#define EEPROM_BBP_SIZE 16 -#define EEPROM_BBP_VALUE FIELD16(0x00ff) -#define EEPROM_BBP_REG_ID FIELD16(0xff00) - -/* - * MCU mailbox commands. - */ -#define MCU_SLEEP 0x30 -#define MCU_WAKEUP 0x31 -#define MCU_RADIO_OFF 0x35 -#define MCU_CURRENT 0x36 -#define MCU_LED 0x50 -#define MCU_LED_STRENGTH 0x51 -#define MCU_LED_1 0x52 -#define MCU_LED_2 0x53 -#define MCU_LED_3 0x54 -#define MCU_RADAR 0x60 -#define MCU_BOOT_SIGNAL 0x72 -#define MCU_BBP_SIGNAL 0x80 -#define MCU_POWER_SAVE 0x83 - -/* - * MCU mailbox tokens - */ -#define TOKEN_WAKUP 3 - -/* - * DMA descriptor defines. - */ -#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) ) -#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) - -/* - * TX WI structure - */ - -/* - * Word0 - * FRAG: 1 To inform TKIP engine this is a fragment. - * MIMO_PS: The remote peer is in dynamic MIMO-PS mode - * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs - * BW: Channel bandwidth 20MHz or 40 MHz - * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED - */ -#define TXWI_W0_FRAG FIELD32(0x00000001) -#define TXWI_W0_MIMO_PS FIELD32(0x00000002) -#define TXWI_W0_CF_ACK FIELD32(0x00000004) -#define TXWI_W0_TS FIELD32(0x00000008) -#define TXWI_W0_AMPDU FIELD32(0x00000010) -#define TXWI_W0_MPDU_DENSITY FIELD32(0x000000e0) -#define TXWI_W0_TX_OP FIELD32(0x00000300) -#define TXWI_W0_MCS FIELD32(0x007f0000) -#define TXWI_W0_BW FIELD32(0x00800000) -#define TXWI_W0_SHORT_GI FIELD32(0x01000000) -#define TXWI_W0_STBC FIELD32(0x06000000) -#define TXWI_W0_IFS FIELD32(0x08000000) -#define TXWI_W0_PHYMODE FIELD32(0xc0000000) - -/* - * Word1 - */ -#define TXWI_W1_ACK FIELD32(0x00000001) -#define TXWI_W1_NSEQ FIELD32(0x00000002) -#define TXWI_W1_BW_WIN_SIZE FIELD32(0x000000fc) -#define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00) -#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) -#define TXWI_W1_PACKETID FIELD32(0xf0000000) - -/* - * Word2 - */ -#define TXWI_W2_IV FIELD32(0xffffffff) - -/* - * Word3 - */ -#define TXWI_W3_EIV FIELD32(0xffffffff) - -/* - * RX WI structure - */ - -/* - * Word0 - */ -#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff) -#define RXWI_W0_KEY_INDEX FIELD32(0x00000300) -#define RXWI_W0_BSSID FIELD32(0x00001c00) -#define RXWI_W0_UDF FIELD32(0x0000e000) -#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) -#define RXWI_W0_TID FIELD32(0xf0000000) - -/* - * Word1 - */ -#define RXWI_W1_FRAG FIELD32(0x0000000f) -#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0) -#define RXWI_W1_MCS FIELD32(0x007f0000) -#define RXWI_W1_BW FIELD32(0x00800000) -#define RXWI_W1_SHORT_GI FIELD32(0x01000000) -#define RXWI_W1_STBC FIELD32(0x06000000) -#define RXWI_W1_PHYMODE FIELD32(0xc0000000) - -/* - * Word2 - */ -#define RXWI_W2_RSSI0 FIELD32(0x000000ff) -#define RXWI_W2_RSSI1 FIELD32(0x0000ff00) -#define RXWI_W2_RSSI2 FIELD32(0x00ff0000) - -/* - * Word3 - */ -#define RXWI_W3_SNR0 FIELD32(0x000000ff) -#define RXWI_W3_SNR1 FIELD32(0x0000ff00) - -/* - * Macros for converting txpower from EEPROM to mac80211 value - * and from mac80211 value to register value. - */ -#define MIN_G_TXPOWER 0 -#define MIN_A_TXPOWER -7 -#define MAX_G_TXPOWER 31 -#define MAX_A_TXPOWER 15 -#define DEFAULT_TXPOWER 5 - -#define TXPOWER_G_FROM_DEV(__txpower) \ - ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) - -#define TXPOWER_G_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER) - -#define TXPOWER_A_FROM_DEV(__txpower) \ - ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) - -#define TXPOWER_A_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER) - -#endif /* RT2800_H */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c deleted file mode 100644 index 5c7d74a6f16e..000000000000 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c +++ /dev/null @@ -1,1817 +0,0 @@ -/* - Copyright (C) 2009 Bartlomiej Zolnierkiewicz - - Based on the original rt2800pci.c and rt2800usb.c: - - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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. - */ - -/* - Module: rt2800lib - Abstract: rt2800 generic device routines. - */ - -#include -#include - -#include "rt2x00.h" -#ifdef CONFIG_RT2800USB -#include "rt2x00usb.h" -#endif -#include "rt2800lib.h" -#include "rt2800.h" -#include "rt2800usb.h" - -MODULE_AUTHOR("Bartlomiej Zolnierkiewicz"); -MODULE_DESCRIPTION("rt2800 library"); -MODULE_LICENSE("GPL"); - -/* - * Register access. - * All access to the CSR registers will go through the methods - * rt2800_register_read and rt2800_register_write. - * BBP and RF register require indirect register access, - * and use the CSR registers BBPCSR and RFCSR to achieve this. - * These indirect registers work with busy bits, - * and we will try maximal REGISTER_BUSY_COUNT times to access - * the register while taking a REGISTER_BUSY_DELAY us delay - * between each attampt. When the busy bit is still set at that time, - * the access attempt is considered to have failed, - * and we will print an error. - * The _lock versions must be used if you already hold the csr_mutex - */ -#define WAIT_FOR_BBP(__dev, __reg) \ - rt2800_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg)) -#define WAIT_FOR_RFCSR(__dev, __reg) \ - rt2800_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg)) -#define WAIT_FOR_RF(__dev, __reg) \ - rt2800_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg)) -#define WAIT_FOR_MCU(__dev, __reg) \ - rt2800_regbusy_read((__dev), H2M_MAILBOX_CSR, \ - H2M_MAILBOX_CSR_OWNER, (__reg)) - -static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u8 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, BBP_CSR_CFG_VALUE, value); - rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); - rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); - rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); - if (rt2x00_intf_is_pci(rt2x00dev)) - rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); - - rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u8 *value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the read request into the register. - * After the data has been written, we wait until hardware - * returns the correct value, if at any time the register - * doesn't become available in time, reg will be 0xffffffff - * which means we return 0xff to the caller. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); - rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); - rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); - if (rt2x00_intf_is_pci(rt2x00dev)) - rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); - - rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); - - WAIT_FOR_BBP(rt2x00dev, ®); - } - - *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE); - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2800_rfcsr_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u8 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the RFCSR becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, RF_CSR_CFG_DATA, value); - rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); - rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 1); - rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); - - rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u8 *value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the RFCSR becomes available, afterwards we - * can safely write the read request into the register. - * After the data has been written, we wait until hardware - * returns the correct value, if at any time the register - * doesn't become available in time, reg will be 0xffffffff - * which means we return 0xff to the caller. - */ - if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); - rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 0); - rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); - - rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); - - WAIT_FOR_RFCSR(rt2x00dev, ®); - } - - *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA); - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u32 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the RF becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_RF(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, RF_CSR_CFG0_REG_VALUE_BW, value); - rt2x00_set_field32(®, RF_CSR_CFG0_STANDBYMODE, 0); - rt2x00_set_field32(®, RF_CSR_CFG0_SEL, 0); - rt2x00_set_field32(®, RF_CSR_CFG0_BUSY, 1); - - rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG0, reg); - rt2x00_rf_write(rt2x00dev, word, value); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, - const u8 command, const u8 token, - const u8 arg0, const u8 arg1) -{ - u32 reg; - - if (rt2x00_intf_is_pci(rt2x00dev)) { - /* - * RT2880 and RT3052 don't support MCU requests. - */ - if (rt2x00_rt(&rt2x00dev->chip, RT2880) || - rt2x00_rt(&rt2x00dev->chip, RT3052)) - return; - } - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the MCU becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_MCU(rt2x00dev, ®)) { - rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); - rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); - rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); - rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); - rt2800_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg); - - reg = 0; - rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); - rt2800_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} -EXPORT_SYMBOL_GPL(rt2800_mcu_request); - -#ifdef CONFIG_RT2X00_LIB_DEBUGFS -const struct rt2x00debug rt2800_rt2x00debug = { - .owner = THIS_MODULE, - .csr = { - .read = rt2800_register_read, - .write = rt2800_register_write, - .flags = RT2X00DEBUGFS_OFFSET, - .word_base = CSR_REG_BASE, - .word_size = sizeof(u32), - .word_count = CSR_REG_SIZE / sizeof(u32), - }, - .eeprom = { - .read = rt2x00_eeprom_read, - .write = rt2x00_eeprom_write, - .word_base = EEPROM_BASE, - .word_size = sizeof(u16), - .word_count = EEPROM_SIZE / sizeof(u16), - }, - .bbp = { - .read = rt2800_bbp_read, - .write = rt2800_bbp_write, - .word_base = BBP_BASE, - .word_size = sizeof(u8), - .word_count = BBP_SIZE / sizeof(u8), - }, - .rf = { - .read = rt2x00_rf_read, - .write = rt2800_rf_write, - .word_base = RF_BASE, - .word_size = sizeof(u32), - .word_count = RF_SIZE / sizeof(u32), - }, -}; -EXPORT_SYMBOL_GPL(rt2800_rt2x00debug); -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ - -int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); - return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); -} -EXPORT_SYMBOL_GPL(rt2800_rfkill_poll); - -#ifdef CONFIG_RT2X00_LIB_LEDS -static void rt2800_brightness_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - unsigned int enabled = brightness != LED_OFF; - unsigned int bg_mode = - (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); - unsigned int polarity = - rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, - EEPROM_FREQ_LED_POLARITY); - unsigned int ledmode = - rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, - EEPROM_FREQ_LED_MODE); - - if (led->type == LED_TYPE_RADIO) { - rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, - enabled ? 0x20 : 0); - } else if (led->type == LED_TYPE_ASSOC) { - rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, - enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); - } else if (led->type == LED_TYPE_QUALITY) { - /* - * The brightness is divided into 6 levels (0 - 5), - * The specs tell us the following levels: - * 0, 1 ,3, 7, 15, 31 - * to determine the level in a simple way we can simply - * work with bitshifting: - * (1 << level) - 1 - */ - rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, - (1 << brightness / (LED_FULL / 6)) - 1, - polarity); - } -} - -static int rt2800_blink_set(struct led_classdev *led_cdev, - unsigned long *delay_on, unsigned long *delay_off) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - u32 reg; - - rt2800_register_read(led->rt2x00dev, LED_CFG, ®); - rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); - rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); - rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); - rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); - rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 12); - rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); - rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); - rt2800_register_write(led->rt2x00dev, LED_CFG, reg); - - return 0; -} - -void rt2800_init_led(struct rt2x00_dev *rt2x00dev, - struct rt2x00_led *led, enum led_type type) -{ - led->rt2x00dev = rt2x00dev; - led->type = type; - led->led_dev.brightness_set = rt2800_brightness_set; - led->led_dev.blink_set = rt2800_blink_set; - led->flags = LED_INITIALIZED; -} -EXPORT_SYMBOL_GPL(rt2800_init_led); -#endif /* CONFIG_RT2X00_LIB_LEDS */ - -/* - * Configuration handlers. - */ -static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key) -{ - struct mac_wcid_entry wcid_entry; - struct mac_iveiv_entry iveiv_entry; - u32 offset; - u32 reg; - - offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); - - rt2800_register_read(rt2x00dev, offset, ®); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, - !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, - (crypto->cmd == SET_KEY) * crypto->cipher); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, - (crypto->cmd == SET_KEY) * crypto->bssidx); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); - rt2800_register_write(rt2x00dev, offset, reg); - - offset = MAC_IVEIV_ENTRY(key->hw_key_idx); - - memset(&iveiv_entry, 0, sizeof(iveiv_entry)); - if ((crypto->cipher == CIPHER_TKIP) || - (crypto->cipher == CIPHER_TKIP_NO_MIC) || - (crypto->cipher == CIPHER_AES)) - iveiv_entry.iv[3] |= 0x20; - iveiv_entry.iv[3] |= key->keyidx << 6; - rt2800_register_multiwrite(rt2x00dev, offset, - &iveiv_entry, sizeof(iveiv_entry)); - - offset = MAC_WCID_ENTRY(key->hw_key_idx); - - memset(&wcid_entry, 0, sizeof(wcid_entry)); - if (crypto->cmd == SET_KEY) - memcpy(&wcid_entry, crypto->address, ETH_ALEN); - rt2800_register_multiwrite(rt2x00dev, offset, - &wcid_entry, sizeof(wcid_entry)); -} - -int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key) -{ - struct hw_key_entry key_entry; - struct rt2x00_field32 field; - u32 offset; - u32 reg; - - if (crypto->cmd == SET_KEY) { - key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx; - - memcpy(key_entry.key, crypto->key, - sizeof(key_entry.key)); - memcpy(key_entry.tx_mic, crypto->tx_mic, - sizeof(key_entry.tx_mic)); - memcpy(key_entry.rx_mic, crypto->rx_mic, - sizeof(key_entry.rx_mic)); - - offset = SHARED_KEY_ENTRY(key->hw_key_idx); - rt2800_register_multiwrite(rt2x00dev, offset, - &key_entry, sizeof(key_entry)); - } - - /* - * The cipher types are stored over multiple registers - * starting with SHARED_KEY_MODE_BASE each word will have - * 32 bits and contains the cipher types for 2 bssidx each. - * Using the correct defines correctly will cause overhead, - * so just calculate the correct offset. - */ - field.bit_offset = 4 * (key->hw_key_idx % 8); - field.bit_mask = 0x7 << field.bit_offset; - - offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); - - rt2800_register_read(rt2x00dev, offset, ®); - rt2x00_set_field32(®, field, - (crypto->cmd == SET_KEY) * crypto->cipher); - rt2800_register_write(rt2x00dev, offset, reg); - - /* - * Update WCID information - */ - rt2800_config_wcid_attr(rt2x00dev, crypto, key); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2800_config_shared_key); - -int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key) -{ - struct hw_key_entry key_entry; - u32 offset; - - if (crypto->cmd == SET_KEY) { - /* - * 1 pairwise key is possible per AID, this means that the AID - * equals our hw_key_idx. Make sure the WCID starts _after_ the - * last possible shared key entry. - */ - if (crypto->aid > (256 - 32)) - return -ENOSPC; - - key->hw_key_idx = 32 + crypto->aid; - - memcpy(key_entry.key, crypto->key, - sizeof(key_entry.key)); - memcpy(key_entry.tx_mic, crypto->tx_mic, - sizeof(key_entry.tx_mic)); - memcpy(key_entry.rx_mic, crypto->rx_mic, - sizeof(key_entry.rx_mic)); - - offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); - rt2800_register_multiwrite(rt2x00dev, offset, - &key_entry, sizeof(key_entry)); - } - - /* - * Update WCID information - */ - rt2800_config_wcid_attr(rt2x00dev, crypto, key); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key); - -void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, - const unsigned int filter_flags) -{ - u32 reg; - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt2800_register_read(rt2x00dev, RX_FILTER_CFG, ®); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CRC_ERROR, - !(filter_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR, - !(filter_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, - !(filter_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST, - !(filter_flags & FIF_ALLMULTI)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BROADCAST, 0); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_DUPLICATE, 1); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END_ACK, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_ACK, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CTS, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_RTS, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, - !(filter_flags & FIF_PSPOLL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 0); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, - !(filter_flags & FIF_CONTROL)); - rt2800_register_write(rt2x00dev, RX_FILTER_CFG, reg); -} -EXPORT_SYMBOL_GPL(rt2800_config_filter); - -void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, - struct rt2x00intf_conf *conf, const unsigned int flags) -{ - unsigned int beacon_base; - u32 reg; - - if (flags & CONFIG_UPDATE_TYPE) { - /* - * Clear current synchronisation setup. - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); - rt2800_register_write(rt2x00dev, beacon_base, 0); - - /* - * Enable synchronisation. - */ - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); - rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); - } - - if (flags & CONFIG_UPDATE_MAC) { - reg = le32_to_cpu(conf->mac[1]); - rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); - conf->mac[1] = cpu_to_le32(reg); - - rt2800_register_multiwrite(rt2x00dev, MAC_ADDR_DW0, - conf->mac, sizeof(conf->mac)); - } - - if (flags & CONFIG_UPDATE_BSSID) { - reg = le32_to_cpu(conf->bssid[1]); - rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 0); - rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0); - conf->bssid[1] = cpu_to_le32(reg); - - rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, - conf->bssid, sizeof(conf->bssid)); - } -} -EXPORT_SYMBOL_GPL(rt2800_config_intf); - -void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp) -{ - u32 reg; - - rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); - rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20); - rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); - - rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); - rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, - !!erp->short_preamble); - rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, - !!erp->short_preamble); - rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg); - - rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); - rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, - erp->cts_protection ? 2 : 0); - rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); - - rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, - erp->basic_rates); - rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); - - rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); - rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); - rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); - rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); - - rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); - rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); - rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); - rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); - rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); - rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); - rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); - - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, - erp->beacon_int * 16); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); -} -EXPORT_SYMBOL_GPL(rt2800_config_erp); - -void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) -{ - u8 r1; - u8 r3; - - rt2800_bbp_read(rt2x00dev, 1, &r1); - rt2800_bbp_read(rt2x00dev, 3, &r3); - - /* - * Configure the TX antenna. - */ - switch ((int)ant->tx) { - case 1: - rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); - if (rt2x00_intf_is_pci(rt2x00dev)) - rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); - break; - case 2: - rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); - break; - case 3: - /* Do nothing */ - break; - } - - /* - * Configure the RX antenna. - */ - switch ((int)ant->rx) { - case 1: - rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); - break; - case 2: - rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); - break; - case 3: - rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); - break; - } - - rt2800_bbp_write(rt2x00dev, 3, r3); - rt2800_bbp_write(rt2x00dev, 1, r1); -} -EXPORT_SYMBOL_GPL(rt2800_config_ant); - -static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u16 eeprom; - short lna_gain; - - if (libconf->rf.channel <= 14) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); - lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG); - } else if (libconf->rf.channel <= 64) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); - lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); - } else if (libconf->rf.channel <= 128) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); - lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); - } else { - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); - lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); - } - - rt2x00dev->lna_gain = lna_gain; -} - -static void rt2800_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf, - struct rf_channel *rf, - struct channel_info *info) -{ - rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); - - if (rt2x00dev->default_ant.tx == 1) - rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); - - if (rt2x00dev->default_ant.rx == 1) { - rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1); - rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); - } else if (rt2x00dev->default_ant.rx == 2) - rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); - - if (rf->channel > 14) { - /* - * When TX power is below 0, we should increase it by 7 to - * make it a positive value (Minumum value is -7). - * However this means that values between 0 and 7 have - * double meaning, and we should set a 7DBm boost flag. - */ - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, - (info->tx_power1 >= 0)); - - if (info->tx_power1 < 0) - info->tx_power1 += 7; - - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, - TXPOWER_A_TO_DEV(info->tx_power1)); - - rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, - (info->tx_power2 >= 0)); - - if (info->tx_power2 < 0) - info->tx_power2 += 7; - - rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, - TXPOWER_A_TO_DEV(info->tx_power2)); - } else { - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, - TXPOWER_G_TO_DEV(info->tx_power1)); - rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, - TXPOWER_G_TO_DEV(info->tx_power2)); - } - - rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); - - rt2800_rf_write(rt2x00dev, 1, rf->rf1); - rt2800_rf_write(rt2x00dev, 2, rf->rf2); - rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); - rt2800_rf_write(rt2x00dev, 4, rf->rf4); - - udelay(200); - - rt2800_rf_write(rt2x00dev, 1, rf->rf1); - rt2800_rf_write(rt2x00dev, 2, rf->rf2); - rt2800_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); - rt2800_rf_write(rt2x00dev, 4, rf->rf4); - - udelay(200); - - rt2800_rf_write(rt2x00dev, 1, rf->rf1); - rt2800_rf_write(rt2x00dev, 2, rf->rf2); - rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); - rt2800_rf_write(rt2x00dev, 4, rf->rf4); -} - -static void rt2800_config_channel_rt3x(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf, - struct rf_channel *rf, - struct channel_info *info) -{ - u8 rfcsr; - - rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); - rt2800_rfcsr_write(rt2x00dev, 2, rf->rf3); - - rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2); - rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); - - rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, - TXPOWER_G_TO_DEV(info->tx_power1)); - rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); - - rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); - rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); - - rt2800_rfcsr_write(rt2x00dev, 24, - rt2x00dev->calibration[conf_is_ht40(conf)]); - - rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); - rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); -} - -static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf, - struct rf_channel *rf, - struct channel_info *info) -{ - u32 reg; - unsigned int tx_pin; - u8 bbp; - - if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) - rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info); - else - rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info); - - /* - * Change BBP settings - */ - rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); - rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); - rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); - rt2800_bbp_write(rt2x00dev, 86, 0); - - if (rf->channel <= 14) { - if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { - rt2800_bbp_write(rt2x00dev, 82, 0x62); - rt2800_bbp_write(rt2x00dev, 75, 0x46); - } else { - rt2800_bbp_write(rt2x00dev, 82, 0x84); - rt2800_bbp_write(rt2x00dev, 75, 0x50); - } - } else { - rt2800_bbp_write(rt2x00dev, 82, 0xf2); - - if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) - rt2800_bbp_write(rt2x00dev, 75, 0x46); - else - rt2800_bbp_write(rt2x00dev, 75, 0x50); - } - - rt2800_register_read(rt2x00dev, TX_BAND_CFG, ®); - rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); - rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14); - rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14); - rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg); - - tx_pin = 0; - - /* Turn on unused PA or LNA when not using 1T or 1R */ - if (rt2x00dev->default_ant.tx != 1) { - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); - } - - /* Turn on unused PA or LNA when not using 1T or 1R */ - if (rt2x00dev->default_ant.rx != 1) { - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); - } - - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14); - - rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); - - rt2800_bbp_read(rt2x00dev, 4, &bbp); - rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); - rt2800_bbp_write(rt2x00dev, 4, bbp); - - rt2800_bbp_read(rt2x00dev, 3, &bbp); - rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); - rt2800_bbp_write(rt2x00dev, 3, bbp); - - if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { - if (conf_is_ht40(conf)) { - rt2800_bbp_write(rt2x00dev, 69, 0x1a); - rt2800_bbp_write(rt2x00dev, 70, 0x0a); - rt2800_bbp_write(rt2x00dev, 73, 0x16); - } else { - rt2800_bbp_write(rt2x00dev, 69, 0x16); - rt2800_bbp_write(rt2x00dev, 70, 0x08); - rt2800_bbp_write(rt2x00dev, 73, 0x11); - } - } - - msleep(1); -} - -static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, - const int txpower) -{ - u32 reg; - u32 value = TXPOWER_G_TO_DEV(txpower); - u8 r1; - - rt2800_bbp_read(rt2x00dev, 1, &r1); - rt2x00_set_field8(®, BBP1_TX_POWER, 0); - rt2800_bbp_write(rt2x00dev, 1, r1); - - rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®); - rt2x00_set_field32(®, TX_PWR_CFG_0_1MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_2MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_55MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_11MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_6MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_9MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_12MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_18MBS, value); - rt2800_register_write(rt2x00dev, TX_PWR_CFG_0, reg); - - rt2800_register_read(rt2x00dev, TX_PWR_CFG_1, ®); - rt2x00_set_field32(®, TX_PWR_CFG_1_24MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_36MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_48MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_54MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_MCS0, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_MCS1, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_MCS2, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_MCS3, value); - rt2800_register_write(rt2x00dev, TX_PWR_CFG_1, reg); - - rt2800_register_read(rt2x00dev, TX_PWR_CFG_2, ®); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS4, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS5, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS6, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS7, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS8, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS9, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS10, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS11, value); - rt2800_register_write(rt2x00dev, TX_PWR_CFG_2, reg); - - rt2800_register_read(rt2x00dev, TX_PWR_CFG_3, ®); - rt2x00_set_field32(®, TX_PWR_CFG_3_MCS12, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_MCS13, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_MCS14, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_MCS15, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN1, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN2, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN3, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN4, value); - rt2800_register_write(rt2x00dev, TX_PWR_CFG_3, reg); - - rt2800_register_read(rt2x00dev, TX_PWR_CFG_4, ®); - rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN5, value); - rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN6, value); - rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN7, value); - rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN8, value); - rt2800_register_write(rt2x00dev, TX_PWR_CFG_4, reg); -} - -static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u32 reg; - - rt2800_register_read(rt2x00dev, TX_RTY_CFG, ®); - rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, - libconf->conf->short_frame_max_tx_count); - rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, - libconf->conf->long_frame_max_tx_count); - rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); - rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); - rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); - rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); - rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg); -} - -static void rt2800_config_ps(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - enum dev_state state = - (libconf->conf->flags & IEEE80211_CONF_PS) ? - STATE_SLEEP : STATE_AWAKE; - u32 reg; - - if (state == STATE_SLEEP) { - rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); - - rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); - rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5); - rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, - libconf->conf->listen_interval - 1); - rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1); - rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); - - rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); - } else { - rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); - - rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); - rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); - rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); - rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); - rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); - } -} - -void rt2800_config(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf, - const unsigned int flags) -{ - /* Always recalculate LNA gain before changing configuration */ - rt2800_config_lna_gain(rt2x00dev, libconf); - - if (flags & IEEE80211_CONF_CHANGE_CHANNEL) - rt2800_config_channel(rt2x00dev, libconf->conf, - &libconf->rf, &libconf->channel); - if (flags & IEEE80211_CONF_CHANGE_POWER) - rt2800_config_txpower(rt2x00dev, libconf->conf->power_level); - if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) - rt2800_config_retry_limit(rt2x00dev, libconf); - if (flags & IEEE80211_CONF_CHANGE_PS) - rt2800_config_ps(rt2x00dev, libconf); -} -EXPORT_SYMBOL_GPL(rt2800_config); - -/* - * Link tuning - */ -void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual) -{ - u32 reg; - - /* - * Update FCS error count from register. - */ - rt2800_register_read(rt2x00dev, RX_STA_CNT0, ®); - qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR); -} -EXPORT_SYMBOL_GPL(rt2800_link_stats); - -static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) -{ - if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { - if (rt2x00_intf_is_usb(rt2x00dev) && - rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) - return 0x1c + (2 * rt2x00dev->lna_gain); - else - return 0x2e + rt2x00dev->lna_gain; - } - - if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) - return 0x32 + (rt2x00dev->lna_gain * 5) / 3; - else - return 0x3a + (rt2x00dev->lna_gain * 5) / 3; -} - -static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual, u8 vgc_level) -{ - if (qual->vgc_level != vgc_level) { - rt2800_bbp_write(rt2x00dev, 66, vgc_level); - qual->vgc_level = vgc_level; - qual->vgc_level_reg = vgc_level; - } -} - -void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual) -{ - rt2800_set_vgc(rt2x00dev, qual, rt2800_get_default_vgc(rt2x00dev)); -} -EXPORT_SYMBOL_GPL(rt2800_reset_tuner); - -void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, - const u32 count) -{ - if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) - return; - - /* - * When RSSI is better then -80 increase VGC level with 0x10 - */ - rt2800_set_vgc(rt2x00dev, qual, - rt2800_get_default_vgc(rt2x00dev) + - ((qual->rssi > -80) * 0x10)); -} -EXPORT_SYMBOL_GPL(rt2800_link_tuner); - -/* - * Initialization functions. - */ -int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - unsigned int i; - - if (rt2x00_intf_is_usb(rt2x00dev)) { - /* - * Wait untill BBP and RF are ready. - */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, MAC_CSR0, ®); - if (reg && reg != ~0) - break; - msleep(1); - } - - if (i == REGISTER_BUSY_COUNT) { - ERROR(rt2x00dev, "Unstable hardware.\n"); - return -EBUSY; - } - - rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, - reg & ~0x00002000); - } else if (rt2x00_intf_is_pci(rt2x00dev)) - rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); - - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); - rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - - if (rt2x00_intf_is_usb(rt2x00dev)) { - rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); -#ifdef CONFIG_RT2800USB - rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, - USB_MODE_RESET, REGISTER_TIMEOUT); -#endif - } - - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); - - rt2800_register_read(rt2x00dev, BCN_OFFSET0, ®); - rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ - rt2x00_set_field32(®, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */ - rt2x00_set_field32(®, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */ - rt2x00_set_field32(®, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */ - rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg); - - rt2800_register_read(rt2x00dev, BCN_OFFSET1, ®); - rt2x00_set_field32(®, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */ - rt2x00_set_field32(®, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */ - rt2x00_set_field32(®, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */ - rt2x00_set_field32(®, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */ - rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg); - - rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); - rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); - - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); - - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, 0); - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, 0); - rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); - rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); - - if (rt2x00_intf_is_usb(rt2x00dev) && - rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { - rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); - rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); - rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); - } else { - rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); - rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); - } - - rt2800_register_read(rt2x00dev, TX_LINK_CFG, ®); - rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32); - rt2x00_set_field32(®, TX_LINK_CFG_MFB_ENABLE, 0); - rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0); - rt2x00_set_field32(®, TX_LINK_CFG_TX_MRQ_EN, 0); - rt2x00_set_field32(®, TX_LINK_CFG_TX_RDG_EN, 0); - rt2x00_set_field32(®, TX_LINK_CFG_TX_CF_ACK_EN, 1); - rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB, 0); - rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFS, 0); - rt2800_register_write(rt2x00dev, TX_LINK_CFG, reg); - - rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); - rt2x00_set_field32(®, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9); - rt2x00_set_field32(®, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10); - rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); - - rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); - rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); - if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION && - rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION) - rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); - else - rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); - rt2x00_set_field32(®, MAX_LEN_CFG_MIN_PSDU, 0); - rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0); - rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg); - - rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f); - - rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); - rt2x00_set_field32(®, AUTO_RSP_CFG_AUTORESPONDER, 1); - rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MMODE, 0); - rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MREF, 0); - rt2x00_set_field32(®, AUTO_RSP_CFG_DUAL_CTS_EN, 0); - rt2x00_set_field32(®, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0); - rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg); - - rt2800_register_read(rt2x00dev, CCK_PROT_CFG, ®); - rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 8); - rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_CTRL, 0); - rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1); - rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg); - - rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); - rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 8); - rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, 0); - rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1); - rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); - - rt2800_register_read(rt2x00dev, MM20_PROT_CFG, ®); - rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_RATE, 0x4004); - rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_CTRL, 0); - rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_NAV, 1); - rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1); - rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); - rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0); - rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0); - rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg); - - rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®); - rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084); - rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, 0); - rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); - rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1); - rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); - rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1); - rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1); - rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg); - - rt2800_register_read(rt2x00dev, GF20_PROT_CFG, ®); - rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_RATE, 0x4004); - rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_CTRL, 0); - rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_NAV, 1); - rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1); - rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); - rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0); - rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0); - rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg); - - rt2800_register_read(rt2x00dev, GF40_PROT_CFG, ®); - rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_RATE, 0x4084); - rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_CTRL, 0); - rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_NAV, 1); - rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1); - rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); - rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1); - rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); - rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg); - - if (rt2x00_intf_is_usb(rt2x00dev)) { - rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); - - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 3); - rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_BIG_ENDIAN, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_HDR_SEG_LEN, 0); - rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - } - - rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f); - rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); - - rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®); - rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); - rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, - IEEE80211_MAX_RTS_THRESHOLD); - rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 0); - rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg); - - rt2800_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); - rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); - - /* - * ASIC will keep garbage value after boot, clear encryption keys. - */ - for (i = 0; i < 4; i++) - rt2800_register_write(rt2x00dev, - SHARED_KEY_MODE_ENTRY(i), 0); - - for (i = 0; i < 256; i++) { - u32 wcid[2] = { 0xffffffff, 0x00ffffff }; - rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), - wcid, sizeof(wcid)); - - rt2800_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); - rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); - } - - /* - * Clear all beacons - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - rt2800_register_write(rt2x00dev, HW_BEACON_BASE0, 0); - rt2800_register_write(rt2x00dev, HW_BEACON_BASE1, 0); - rt2800_register_write(rt2x00dev, HW_BEACON_BASE2, 0); - rt2800_register_write(rt2x00dev, HW_BEACON_BASE3, 0); - rt2800_register_write(rt2x00dev, HW_BEACON_BASE4, 0); - rt2800_register_write(rt2x00dev, HW_BEACON_BASE5, 0); - rt2800_register_write(rt2x00dev, HW_BEACON_BASE6, 0); - rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0); - - if (rt2x00_intf_is_usb(rt2x00dev)) { - rt2800_register_read(rt2x00dev, USB_CYC_CFG, ®); - rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30); - rt2800_register_write(rt2x00dev, USB_CYC_CFG, reg); - } - - rt2800_register_read(rt2x00dev, HT_FBK_CFG0, ®); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS0FBK, 0); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS1FBK, 0); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS2FBK, 1); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS3FBK, 2); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS4FBK, 3); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS5FBK, 4); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS6FBK, 5); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS7FBK, 6); - rt2800_register_write(rt2x00dev, HT_FBK_CFG0, reg); - - rt2800_register_read(rt2x00dev, HT_FBK_CFG1, ®); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS8FBK, 8); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS9FBK, 8); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS10FBK, 9); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS11FBK, 10); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS12FBK, 11); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS13FBK, 12); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS14FBK, 13); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS15FBK, 14); - rt2800_register_write(rt2x00dev, HT_FBK_CFG1, reg); - - rt2800_register_read(rt2x00dev, LG_FBK_CFG0, ®); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 9); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 10); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 11); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 12); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS6FBK, 13); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS7FBK, 14); - rt2800_register_write(rt2x00dev, LG_FBK_CFG0, reg); - - rt2800_register_read(rt2x00dev, LG_FBK_CFG1, ®); - rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS0FBK, 0); - rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS1FBK, 0); - rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS2FBK, 1); - rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS3FBK, 2); - rt2800_register_write(rt2x00dev, LG_FBK_CFG1, reg); - - /* - * We must clear the error counters. - * These registers are cleared on read, - * so we may pass a useless variable to store the value. - */ - rt2800_register_read(rt2x00dev, RX_STA_CNT0, ®); - rt2800_register_read(rt2x00dev, RX_STA_CNT1, ®); - rt2800_register_read(rt2x00dev, RX_STA_CNT2, ®); - rt2800_register_read(rt2x00dev, TX_STA_CNT0, ®); - rt2800_register_read(rt2x00dev, TX_STA_CNT1, ®); - rt2800_register_read(rt2x00dev, TX_STA_CNT2, ®); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2800_init_registers); - -static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u32 reg; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, MAC_STATUS_CFG, ®); - if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY)) - return 0; - - udelay(REGISTER_BUSY_DELAY); - } - - ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n"); - return -EACCES; -} - -static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u8 value; - - /* - * BBP was enabled after firmware was loaded, - * but we need to reactivate it now. - */ - rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); - msleep(1); - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_bbp_read(rt2x00dev, 0, &value); - if ((value != 0xff) && (value != 0x00)) - return 0; - udelay(REGISTER_BUSY_DELAY); - } - - ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); - return -EACCES; -} - -int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u16 eeprom; - u8 reg_id; - u8 value; - - if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev) || - rt2800_wait_bbp_ready(rt2x00dev))) - return -EACCES; - - rt2800_bbp_write(rt2x00dev, 65, 0x2c); - rt2800_bbp_write(rt2x00dev, 66, 0x38); - rt2800_bbp_write(rt2x00dev, 69, 0x12); - rt2800_bbp_write(rt2x00dev, 70, 0x0a); - rt2800_bbp_write(rt2x00dev, 73, 0x10); - rt2800_bbp_write(rt2x00dev, 81, 0x37); - rt2800_bbp_write(rt2x00dev, 82, 0x62); - rt2800_bbp_write(rt2x00dev, 83, 0x6a); - rt2800_bbp_write(rt2x00dev, 84, 0x99); - rt2800_bbp_write(rt2x00dev, 86, 0x00); - rt2800_bbp_write(rt2x00dev, 91, 0x04); - rt2800_bbp_write(rt2x00dev, 92, 0x00); - rt2800_bbp_write(rt2x00dev, 103, 0x00); - rt2800_bbp_write(rt2x00dev, 105, 0x05); - - if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { - rt2800_bbp_write(rt2x00dev, 69, 0x16); - rt2800_bbp_write(rt2x00dev, 73, 0x12); - } - - if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) - rt2800_bbp_write(rt2x00dev, 84, 0x19); - - if (rt2x00_intf_is_usb(rt2x00dev) && - rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { - rt2800_bbp_write(rt2x00dev, 70, 0x0a); - rt2800_bbp_write(rt2x00dev, 84, 0x99); - rt2800_bbp_write(rt2x00dev, 105, 0x05); - } - - if (rt2x00_intf_is_pci(rt2x00dev) && - rt2x00_rt(&rt2x00dev->chip, RT3052)) { - rt2800_bbp_write(rt2x00dev, 31, 0x08); - rt2800_bbp_write(rt2x00dev, 78, 0x0e); - rt2800_bbp_write(rt2x00dev, 80, 0x08); - } - - for (i = 0; i < EEPROM_BBP_SIZE; i++) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); - - if (eeprom != 0xffff && eeprom != 0x0000) { - reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); - value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); - rt2800_bbp_write(rt2x00dev, reg_id, value); - } - } - - return 0; -} -EXPORT_SYMBOL_GPL(rt2800_init_bbp); - -static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, - bool bw40, u8 rfcsr24, u8 filter_target) -{ - unsigned int i; - u8 bbp; - u8 rfcsr; - u8 passband; - u8 stopband; - u8 overtuned = 0; - - rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24); - - rt2800_bbp_read(rt2x00dev, 4, &bbp); - rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40); - rt2800_bbp_write(rt2x00dev, 4, bbp); - - rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1); - rt2800_rfcsr_write(rt2x00dev, 22, rfcsr); - - /* - * Set power & frequency of passband test tone - */ - rt2800_bbp_write(rt2x00dev, 24, 0); - - for (i = 0; i < 100; i++) { - rt2800_bbp_write(rt2x00dev, 25, 0x90); - msleep(1); - - rt2800_bbp_read(rt2x00dev, 55, &passband); - if (passband) - break; - } - - /* - * Set power & frequency of stopband test tone - */ - rt2800_bbp_write(rt2x00dev, 24, 0x06); - - for (i = 0; i < 100; i++) { - rt2800_bbp_write(rt2x00dev, 25, 0x90); - msleep(1); - - rt2800_bbp_read(rt2x00dev, 55, &stopband); - - if ((passband - stopband) <= filter_target) { - rfcsr24++; - overtuned += ((passband - stopband) == filter_target); - } else - break; - - rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24); - } - - rfcsr24 -= !!overtuned; - - rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24); - return rfcsr24; -} - -int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) -{ - u8 rfcsr; - u8 bbp; - - if (rt2x00_intf_is_usb(rt2x00dev) && - rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) - return 0; - - if (rt2x00_intf_is_pci(rt2x00dev)) { - if (!rt2x00_rf(&rt2x00dev->chip, RF3020) && - !rt2x00_rf(&rt2x00dev->chip, RF3021) && - !rt2x00_rf(&rt2x00dev->chip, RF3022)) - return 0; - } - - /* - * Init RF calibration. - */ - rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); - rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); - msleep(1); - rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); - rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); - - if (rt2x00_intf_is_usb(rt2x00dev)) { - rt2800_rfcsr_write(rt2x00dev, 4, 0x40); - rt2800_rfcsr_write(rt2x00dev, 5, 0x03); - rt2800_rfcsr_write(rt2x00dev, 6, 0x02); - rt2800_rfcsr_write(rt2x00dev, 7, 0x70); - rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); - rt2800_rfcsr_write(rt2x00dev, 10, 0x71); - rt2800_rfcsr_write(rt2x00dev, 11, 0x21); - rt2800_rfcsr_write(rt2x00dev, 12, 0x7b); - rt2800_rfcsr_write(rt2x00dev, 14, 0x90); - rt2800_rfcsr_write(rt2x00dev, 15, 0x58); - rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); - rt2800_rfcsr_write(rt2x00dev, 17, 0x92); - rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); - rt2800_rfcsr_write(rt2x00dev, 19, 0x02); - rt2800_rfcsr_write(rt2x00dev, 20, 0xba); - rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); - rt2800_rfcsr_write(rt2x00dev, 24, 0x16); - rt2800_rfcsr_write(rt2x00dev, 25, 0x01); - rt2800_rfcsr_write(rt2x00dev, 27, 0x03); - rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); - } else if (rt2x00_intf_is_pci(rt2x00dev)) { - rt2800_rfcsr_write(rt2x00dev, 0, 0x50); - rt2800_rfcsr_write(rt2x00dev, 1, 0x01); - rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); - rt2800_rfcsr_write(rt2x00dev, 3, 0x75); - rt2800_rfcsr_write(rt2x00dev, 4, 0x40); - rt2800_rfcsr_write(rt2x00dev, 5, 0x03); - rt2800_rfcsr_write(rt2x00dev, 6, 0x02); - rt2800_rfcsr_write(rt2x00dev, 7, 0x50); - rt2800_rfcsr_write(rt2x00dev, 8, 0x39); - rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); - rt2800_rfcsr_write(rt2x00dev, 10, 0x60); - rt2800_rfcsr_write(rt2x00dev, 11, 0x21); - rt2800_rfcsr_write(rt2x00dev, 12, 0x75); - rt2800_rfcsr_write(rt2x00dev, 13, 0x75); - rt2800_rfcsr_write(rt2x00dev, 14, 0x90); - rt2800_rfcsr_write(rt2x00dev, 15, 0x58); - rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); - rt2800_rfcsr_write(rt2x00dev, 17, 0x92); - rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); - rt2800_rfcsr_write(rt2x00dev, 19, 0x02); - rt2800_rfcsr_write(rt2x00dev, 20, 0xba); - rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); - rt2800_rfcsr_write(rt2x00dev, 22, 0x00); - rt2800_rfcsr_write(rt2x00dev, 23, 0x31); - rt2800_rfcsr_write(rt2x00dev, 24, 0x08); - rt2800_rfcsr_write(rt2x00dev, 25, 0x01); - rt2800_rfcsr_write(rt2x00dev, 26, 0x25); - rt2800_rfcsr_write(rt2x00dev, 27, 0x23); - rt2800_rfcsr_write(rt2x00dev, 28, 0x13); - rt2800_rfcsr_write(rt2x00dev, 29, 0x83); - } - - /* - * Set RX Filter calibration for 20MHz and 40MHz - */ - rt2x00dev->calibration[0] = - rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16); - rt2x00dev->calibration[1] = - rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); - - /* - * Set back to initial state - */ - rt2800_bbp_write(rt2x00dev, 24, 0); - - rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0); - rt2800_rfcsr_write(rt2x00dev, 22, rfcsr); - - /* - * set BBP back to BW20 - */ - rt2800_bbp_read(rt2x00dev, 4, &bbp); - rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0); - rt2800_bbp_write(rt2x00dev, 4, bbp); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2800_init_rfcsr); - -/* - * IEEE80211 stack callback functions. - */ -static void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, - u32 *iv32, u16 *iv16) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct mac_iveiv_entry iveiv_entry; - u32 offset; - - offset = MAC_IVEIV_ENTRY(hw_key_idx); - rt2800_register_multiread(rt2x00dev, offset, - &iveiv_entry, sizeof(iveiv_entry)); - - memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16)); - memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32)); -} - -static int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u32 reg; - bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD); - - rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®); - rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, value); - rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg); - - rt2800_register_read(rt2x00dev, CCK_PROT_CFG, ®); - rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, enabled); - rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg); - - rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); - rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, enabled); - rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); - - rt2800_register_read(rt2x00dev, MM20_PROT_CFG, ®); - rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, enabled); - rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg); - - rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®); - rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, enabled); - rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg); - - rt2800_register_read(rt2x00dev, GF20_PROT_CFG, ®); - rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, enabled); - rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg); - - rt2800_register_read(rt2x00dev, GF40_PROT_CFG, ®); - rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, enabled); - rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg); - - return 0; -} - -static int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, - const struct ieee80211_tx_queue_params *params) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct data_queue *queue; - struct rt2x00_field32 field; - int retval; - u32 reg; - u32 offset; - - /* - * First pass the configuration through rt2x00lib, that will - * update the queue settings and validate the input. After that - * we are free to update the registers based on the value - * in the queue parameter. - */ - retval = rt2x00mac_conf_tx(hw, queue_idx, params); - if (retval) - return retval; - - /* - * We only need to perform additional register initialization - * for WMM queues/ - */ - if (queue_idx >= 4) - return 0; - - queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); - - /* Update WMM TXOP register */ - offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2))); - field.bit_offset = (queue_idx & 1) * 16; - field.bit_mask = 0xffff << field.bit_offset; - - rt2800_register_read(rt2x00dev, offset, ®); - rt2x00_set_field32(®, field, queue->txop); - rt2800_register_write(rt2x00dev, offset, reg); - - /* Update WMM registers */ - field.bit_offset = queue_idx * 4; - field.bit_mask = 0xf << field.bit_offset; - - rt2800_register_read(rt2x00dev, WMM_AIFSN_CFG, ®); - rt2x00_set_field32(®, field, queue->aifs); - rt2800_register_write(rt2x00dev, WMM_AIFSN_CFG, reg); - - rt2800_register_read(rt2x00dev, WMM_CWMIN_CFG, ®); - rt2x00_set_field32(®, field, queue->cw_min); - rt2800_register_write(rt2x00dev, WMM_CWMIN_CFG, reg); - - rt2800_register_read(rt2x00dev, WMM_CWMAX_CFG, ®); - rt2x00_set_field32(®, field, queue->cw_max); - rt2800_register_write(rt2x00dev, WMM_CWMAX_CFG, reg); - - /* Update EDCA registers */ - offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx); - - rt2800_register_read(rt2x00dev, offset, ®); - rt2x00_set_field32(®, EDCA_AC0_CFG_TX_OP, queue->txop); - rt2x00_set_field32(®, EDCA_AC0_CFG_AIFSN, queue->aifs); - rt2x00_set_field32(®, EDCA_AC0_CFG_CWMIN, queue->cw_min); - rt2x00_set_field32(®, EDCA_AC0_CFG_CWMAX, queue->cw_max); - rt2800_register_write(rt2x00dev, offset, reg); - - return 0; -} - -static u64 rt2800_get_tsf(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u64 tsf; - u32 reg; - - rt2800_register_read(rt2x00dev, TSF_TIMER_DW1, ®); - tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32; - rt2800_register_read(rt2x00dev, TSF_TIMER_DW0, ®); - tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD); - - return tsf; -} - -const struct ieee80211_ops rt2800_mac80211_ops = { - .tx = rt2x00mac_tx, - .start = rt2x00mac_start, - .stop = rt2x00mac_stop, - .add_interface = rt2x00mac_add_interface, - .remove_interface = rt2x00mac_remove_interface, - .config = rt2x00mac_config, - .configure_filter = rt2x00mac_configure_filter, - .set_tim = rt2x00mac_set_tim, - .set_key = rt2x00mac_set_key, - .get_stats = rt2x00mac_get_stats, - .get_tkip_seq = rt2800_get_tkip_seq, - .set_rts_threshold = rt2800_set_rts_threshold, - .bss_info_changed = rt2x00mac_bss_info_changed, - .conf_tx = rt2800_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, - .get_tsf = rt2800_get_tsf, - .rfkill_poll = rt2x00mac_rfkill_poll, -}; -EXPORT_SYMBOL_GPL(rt2800_mac80211_ops); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.h b/trunk/drivers/net/wireless/rt2x00/rt2800lib.h deleted file mode 100644 index 5eea8fcba6cc..000000000000 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - Copyright (C) 2009 Bartlomiej Zolnierkiewicz - - 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. - */ - -#ifndef RT2800LIB_H -#define RT2800LIB_H - -struct rt2800_ops { - void (*register_read)(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, u32 *value); - void (*register_write)(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, u32 value); - void (*register_write_lock)(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, u32 value); - - void (*register_multiread)(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - void *value, const u32 length); - void (*register_multiwrite)(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - const void *value, const u32 length); - - int (*regbusy_read)(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - const struct rt2x00_field32 field, u32 *reg); -}; - -static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u32 *value) -{ - const struct rt2800_ops *rt2800ops = rt2x00dev->priv; - - rt2800ops->register_read(rt2x00dev, offset, value); -} - -static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u32 value) -{ - const struct rt2800_ops *rt2800ops = rt2x00dev->priv; - - rt2800ops->register_write(rt2x00dev, offset, value); -} - -static inline void rt2800_register_write_lock(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u32 value) -{ - const struct rt2800_ops *rt2800ops = rt2x00dev->priv; - - rt2800ops->register_write_lock(rt2x00dev, offset, value); -} - -static inline void rt2800_register_multiread(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - void *value, const u32 length) -{ - const struct rt2800_ops *rt2800ops = rt2x00dev->priv; - - rt2800ops->register_multiread(rt2x00dev, offset, value, length); -} - -static inline void rt2800_register_multiwrite(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - const void *value, - const u32 length) -{ - const struct rt2800_ops *rt2800ops = rt2x00dev->priv; - - rt2800ops->register_multiwrite(rt2x00dev, offset, value, length); -} - -static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - const struct rt2x00_field32 field, - u32 *reg) -{ - const struct rt2800_ops *rt2800ops = rt2x00dev->priv; - - return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg); -} - -void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, - const u8 command, const u8 token, - const u8 arg0, const u8 arg1); - -extern const struct rt2x00debug rt2800_rt2x00debug; - -int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev); -void rt2800_init_led(struct rt2x00_dev *rt2x00dev, - struct rt2x00_led *led, enum led_type type); -int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key); -int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key); -void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, - const unsigned int filter_flags); -void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, - struct rt2x00intf_conf *conf, const unsigned int flags); -void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp); -void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant); -void rt2800_config(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf, - const unsigned int flags); -void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual); -void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual); -void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, - const u32 count); - -int rt2800_init_registers(struct rt2x00_dev *rt2x00dev); -int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev); -int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev); - -extern const struct ieee80211_ops rt2800_mac80211_ops; - -#endif /* RT2800LIB_H */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c index 3c5b875cdee8..be81788b80c7 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c @@ -37,8 +37,6 @@ #include "rt2x00.h" #include "rt2x00pci.h" #include "rt2x00soc.h" -#include "rt2800lib.h" -#include "rt2800.h" #include "rt2800pci.h" #ifdef CONFIG_RT2800PCI_PCI_MODULE @@ -56,13 +54,205 @@ static int modparam_nohwcrypt = 1; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); +/* + * Register access. + * BBP and RF register require indirect register access, + * and use the CSR registers PHY_CSR3 and PHY_CSR4 to achieve this. + * These indirect registers work with busy bits, + * and we will try maximal REGISTER_BUSY_COUNT times to access + * the register while taking a REGISTER_BUSY_DELAY us delay + * between each attampt. When the busy bit is still set at that time, + * the access attempt is considered to have failed, + * and we will print an error. + */ +#define WAIT_FOR_BBP(__dev, __reg) \ + rt2x00pci_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg)) +#define WAIT_FOR_RFCSR(__dev, __reg) \ + rt2x00pci_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg)) +#define WAIT_FOR_RF(__dev, __reg) \ + rt2x00pci_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg)) +#define WAIT_FOR_MCU(__dev, __reg) \ + rt2x00pci_regbusy_read((__dev), H2M_MAILBOX_CSR, \ + H2M_MAILBOX_CSR_OWNER, (__reg)) + +static void rt2800pci_bbp_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u8 value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the BBP becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, BBP_CSR_CFG_VALUE, value); + rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); + rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); + rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); + + rt2x00pci_register_write(rt2x00dev, BBP_CSR_CFG, reg); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800pci_bbp_read(struct rt2x00_dev *rt2x00dev, + const unsigned int word, u8 *value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the BBP becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. + */ + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); + rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); + rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); + + rt2x00pci_register_write(rt2x00dev, BBP_CSR_CFG, reg); + + WAIT_FOR_BBP(rt2x00dev, ®); + } + + *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE); + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800pci_rfcsr_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u8 value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the RFCSR becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RF_CSR_CFG_DATA, value); + rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 1); + rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); + + rt2x00pci_register_write(rt2x00dev, RF_CSR_CFG, reg); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800pci_rfcsr_read(struct rt2x00_dev *rt2x00dev, + const unsigned int word, u8 *value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the RFCSR becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. + */ + if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 0); + rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); + + rt2x00pci_register_write(rt2x00dev, RF_CSR_CFG, reg); + + WAIT_FOR_RFCSR(rt2x00dev, ®); + } + + *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA); + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800pci_rf_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u32 value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the RF becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_RF(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RF_CSR_CFG0_REG_VALUE_BW, value); + rt2x00_set_field32(®, RF_CSR_CFG0_STANDBYMODE, 0); + rt2x00_set_field32(®, RF_CSR_CFG0_SEL, 0); + rt2x00_set_field32(®, RF_CSR_CFG0_BUSY, 1); + + rt2x00pci_register_write(rt2x00dev, RF_CSR_CFG0, reg); + rt2x00_rf_write(rt2x00dev, word, value); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800pci_mcu_request(struct rt2x00_dev *rt2x00dev, + const u8 command, const u8 token, + const u8 arg0, const u8 arg1) +{ + u32 reg; + + /* + * RT2880 and RT3052 don't support MCU requests. + */ + if (rt2x00_rt(&rt2x00dev->chip, RT2880) || + rt2x00_rt(&rt2x00dev->chip, RT3052)) + return; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the MCU becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_MCU(rt2x00dev, ®)) { + rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); + rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg); + + reg = 0; + rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); + rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) { unsigned int i; u32 reg; for (i = 0; i < 200; i++) { - rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); + rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) || (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || @@ -76,8 +266,8 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) if (i == 200) ERROR(rt2x00dev, "MCU request failed, no response from hardware\n"); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); + rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); + rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); } #ifdef CONFIG_RT2800PCI_WISOC @@ -99,7 +289,7 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) struct rt2x00_dev *rt2x00dev = eeprom->data; u32 reg; - rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); + rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN); eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT); @@ -121,7 +311,7 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom) rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT, !!eeprom->reg_chip_select); - rt2800_register_write(rt2x00dev, E2PROM_CSR, reg); + rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); } static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) @@ -129,7 +319,7 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) struct eeprom_93cx6 eeprom; u32 reg; - rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); + rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); eeprom.data = rt2x00dev; eeprom.register_read = rt2800pci_eepromregister_read; @@ -150,23 +340,23 @@ static void rt2800pci_efuse_read(struct rt2x00_dev *rt2x00dev, { u32 reg; - rt2800_register_read(rt2x00dev, EFUSE_CTRL, ®); + rt2x00pci_register_read(rt2x00dev, EFUSE_CTRL, ®); rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i); rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0); rt2x00_set_field32(®, EFUSE_CTRL_KICK, 1); - rt2800_register_write(rt2x00dev, EFUSE_CTRL, reg); + rt2x00pci_register_write(rt2x00dev, EFUSE_CTRL, reg); /* Wait until the EEPROM has been loaded */ - rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, ®); + rt2x00pci_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, ®); /* Apparently the data is read from end to start */ - rt2800_register_read(rt2x00dev, EFUSE_DATA3, + rt2x00pci_register_read(rt2x00dev, EFUSE_DATA3, (u32 *)&rt2x00dev->eeprom[i]); - rt2800_register_read(rt2x00dev, EFUSE_DATA2, + rt2x00pci_register_read(rt2x00dev, EFUSE_DATA2, (u32 *)&rt2x00dev->eeprom[i + 2]); - rt2800_register_read(rt2x00dev, EFUSE_DATA1, + rt2x00pci_register_read(rt2x00dev, EFUSE_DATA1, (u32 *)&rt2x00dev->eeprom[i + 4]); - rt2800_register_read(rt2x00dev, EFUSE_DATA0, + rt2x00pci_register_read(rt2x00dev, EFUSE_DATA0, (u32 *)&rt2x00dev->eeprom[i + 6]); } @@ -187,6 +377,829 @@ static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) } #endif /* CONFIG_RT2800PCI_PCI */ +#ifdef CONFIG_RT2X00_LIB_DEBUGFS +static const struct rt2x00debug rt2800pci_rt2x00debug = { + .owner = THIS_MODULE, + .csr = { + .read = rt2x00pci_register_read, + .write = rt2x00pci_register_write, + .flags = RT2X00DEBUGFS_OFFSET, + .word_base = CSR_REG_BASE, + .word_size = sizeof(u32), + .word_count = CSR_REG_SIZE / sizeof(u32), + }, + .eeprom = { + .read = rt2x00_eeprom_read, + .write = rt2x00_eeprom_write, + .word_base = EEPROM_BASE, + .word_size = sizeof(u16), + .word_count = EEPROM_SIZE / sizeof(u16), + }, + .bbp = { + .read = rt2800pci_bbp_read, + .write = rt2800pci_bbp_write, + .word_base = BBP_BASE, + .word_size = sizeof(u8), + .word_count = BBP_SIZE / sizeof(u8), + }, + .rf = { + .read = rt2x00_rf_read, + .write = rt2800pci_rf_write, + .word_base = RF_BASE, + .word_size = sizeof(u32), + .word_count = RF_SIZE / sizeof(u32), + }, +}; +#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ + +static int rt2800pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + + rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); +} + +#ifdef CONFIG_RT2X00_LIB_LEDS +static void rt2800pci_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + unsigned int enabled = brightness != LED_OFF; + unsigned int bg_mode = + (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); + unsigned int polarity = + rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, + EEPROM_FREQ_LED_POLARITY); + unsigned int ledmode = + rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, + EEPROM_FREQ_LED_MODE); + + if (led->type == LED_TYPE_RADIO) { + rt2800pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, + enabled ? 0x20 : 0); + } else if (led->type == LED_TYPE_ASSOC) { + rt2800pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, + enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); + } else if (led->type == LED_TYPE_QUALITY) { + /* + * The brightness is divided into 6 levels (0 - 5), + * The specs tell us the following levels: + * 0, 1 ,3, 7, 15, 31 + * to determine the level in a simple way we can simply + * work with bitshifting: + * (1 << level) - 1 + */ + rt2800pci_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, + (1 << brightness / (LED_FULL / 6)) - 1, + polarity); + } +} + +static int rt2800pci_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + u32 reg; + + rt2x00pci_register_read(led->rt2x00dev, LED_CFG, ®); + rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); + rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); + rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); + rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); + rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 12); + rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); + rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); + rt2x00pci_register_write(led->rt2x00dev, LED_CFG, reg); + + return 0; +} + +static void rt2800pci_init_led(struct rt2x00_dev *rt2x00dev, + struct rt2x00_led *led, + enum led_type type) +{ + led->rt2x00dev = rt2x00dev; + led->type = type; + led->led_dev.brightness_set = rt2800pci_brightness_set; + led->led_dev.blink_set = rt2800pci_blink_set; + led->flags = LED_INITIALIZED; +} +#endif /* CONFIG_RT2X00_LIB_LEDS */ + +/* + * Configuration handlers. + */ +static void rt2800pci_config_wcid_attr(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) +{ + struct mac_wcid_entry wcid_entry; + struct mac_iveiv_entry iveiv_entry; + u32 offset; + u32 reg; + + offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); + + rt2x00pci_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, + !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, + (crypto->cmd == SET_KEY) * crypto->cipher); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, + (crypto->cmd == SET_KEY) * crypto->bssidx); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); + rt2x00pci_register_write(rt2x00dev, offset, reg); + + offset = MAC_IVEIV_ENTRY(key->hw_key_idx); + + memset(&iveiv_entry, 0, sizeof(iveiv_entry)); + if ((crypto->cipher == CIPHER_TKIP) || + (crypto->cipher == CIPHER_TKIP_NO_MIC) || + (crypto->cipher == CIPHER_AES)) + iveiv_entry.iv[3] |= 0x20; + iveiv_entry.iv[3] |= key->keyidx << 6; + rt2x00pci_register_multiwrite(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); + + offset = MAC_WCID_ENTRY(key->hw_key_idx); + + memset(&wcid_entry, 0, sizeof(wcid_entry)); + if (crypto->cmd == SET_KEY) + memcpy(&wcid_entry, crypto->address, ETH_ALEN); + rt2x00pci_register_multiwrite(rt2x00dev, offset, + &wcid_entry, sizeof(wcid_entry)); +} + +static int rt2800pci_config_shared_key(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) +{ + struct hw_key_entry key_entry; + struct rt2x00_field32 field; + u32 offset; + u32 reg; + + if (crypto->cmd == SET_KEY) { + key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx; + + memcpy(key_entry.key, crypto->key, + sizeof(key_entry.key)); + memcpy(key_entry.tx_mic, crypto->tx_mic, + sizeof(key_entry.tx_mic)); + memcpy(key_entry.rx_mic, crypto->rx_mic, + sizeof(key_entry.rx_mic)); + + offset = SHARED_KEY_ENTRY(key->hw_key_idx); + rt2x00pci_register_multiwrite(rt2x00dev, offset, + &key_entry, sizeof(key_entry)); + } + + /* + * The cipher types are stored over multiple registers + * starting with SHARED_KEY_MODE_BASE each word will have + * 32 bits and contains the cipher types for 2 bssidx each. + * Using the correct defines correctly will cause overhead, + * so just calculate the correct offset. + */ + field.bit_offset = 4 * (key->hw_key_idx % 8); + field.bit_mask = 0x7 << field.bit_offset; + + offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); + + rt2x00pci_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, field, + (crypto->cmd == SET_KEY) * crypto->cipher); + rt2x00pci_register_write(rt2x00dev, offset, reg); + + /* + * Update WCID information + */ + rt2800pci_config_wcid_attr(rt2x00dev, crypto, key); + + return 0; +} + +static int rt2800pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) +{ + struct hw_key_entry key_entry; + u32 offset; + + if (crypto->cmd == SET_KEY) { + /* + * 1 pairwise key is possible per AID, this means that the AID + * equals our hw_key_idx. Make sure the WCID starts _after_ the + * last possible shared key entry. + */ + if (crypto->aid > (256 - 32)) + return -ENOSPC; + + key->hw_key_idx = 32 + crypto->aid; + + + memcpy(key_entry.key, crypto->key, + sizeof(key_entry.key)); + memcpy(key_entry.tx_mic, crypto->tx_mic, + sizeof(key_entry.tx_mic)); + memcpy(key_entry.rx_mic, crypto->rx_mic, + sizeof(key_entry.rx_mic)); + + offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); + rt2x00pci_register_multiwrite(rt2x00dev, offset, + &key_entry, sizeof(key_entry)); + } + + /* + * Update WCID information + */ + rt2800pci_config_wcid_attr(rt2x00dev, crypto, key); + + return 0; +} + +static void rt2800pci_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u32 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt2x00pci_register_read(rt2x00dev, RX_FILTER_CFG, ®); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CRC_ERROR, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST, + !(filter_flags & FIF_ALLMULTI)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BROADCAST, 0); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_DUPLICATE, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END_ACK, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_ACK, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CTS, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_RTS, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, + !(filter_flags & FIF_PSPOLL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 0); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, + !(filter_flags & FIF_CONTROL)); + rt2x00pci_register_write(rt2x00dev, RX_FILTER_CFG, reg); +} + +static void rt2800pci_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) +{ + unsigned int beacon_base; + u32 reg; + + if (flags & CONFIG_UPDATE_TYPE) { + /* + * Clear current synchronisation setup. + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); + rt2x00pci_register_write(rt2x00dev, beacon_base, 0); + + /* + * Enable synchronisation. + */ + rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); + rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); + } + + if (flags & CONFIG_UPDATE_MAC) { + reg = le32_to_cpu(conf->mac[1]); + rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); + conf->mac[1] = cpu_to_le32(reg); + + rt2x00pci_register_multiwrite(rt2x00dev, MAC_ADDR_DW0, + conf->mac, sizeof(conf->mac)); + } + + if (flags & CONFIG_UPDATE_BSSID) { + reg = le32_to_cpu(conf->bssid[1]); + rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 0); + rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0); + conf->bssid[1] = cpu_to_le32(reg); + + rt2x00pci_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, + conf->bssid, sizeof(conf->bssid)); + } +} + +static void rt2800pci_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) +{ + u32 reg; + + rt2x00pci_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20); + rt2x00pci_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, AUTO_RSP_CFG, ®); + rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, + !!erp->short_preamble); + rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, + !!erp->short_preamble); + rt2x00pci_register_write(rt2x00dev, AUTO_RSP_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, OFDM_PROT_CFG, ®); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, + erp->cts_protection ? 2 : 0); + rt2x00pci_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + + rt2x00pci_register_write(rt2x00dev, LEGACY_BASIC_RATE, + erp->basic_rates); + rt2x00pci_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); + + rt2x00pci_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); + rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); + rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); + rt2x00pci_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, XIFS_TIME_CFG, ®); + rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); + rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); + rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); + rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); + rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); + rt2x00pci_register_write(rt2x00dev, XIFS_TIME_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, + erp->beacon_int * 16); + rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); +} + +static void rt2800pci_config_ant(struct rt2x00_dev *rt2x00dev, + struct antenna_setup *ant) +{ + u8 r1; + u8 r3; + + rt2800pci_bbp_read(rt2x00dev, 1, &r1); + rt2800pci_bbp_read(rt2x00dev, 3, &r3); + + /* + * Configure the TX antenna. + */ + switch ((int)ant->tx) { + case 1: + rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); + break; + case 2: + rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); + break; + case 3: + /* Do nothing */ + break; + } + + /* + * Configure the RX antenna. + */ + switch ((int)ant->rx) { + case 1: + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); + break; + case 2: + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); + break; + case 3: + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); + break; + } + + rt2800pci_bbp_write(rt2x00dev, 3, r3); + rt2800pci_bbp_write(rt2x00dev, 1, r1); +} + +static void rt2800pci_config_lna_gain(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + u16 eeprom; + short lna_gain; + + if (libconf->rf.channel <= 14) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG); + } else if (libconf->rf.channel <= 64) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); + } else if (libconf->rf.channel <= 128) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); + } else { + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); + } + + rt2x00dev->lna_gain = lna_gain; +} + +static void rt2800pci_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); + + if (rt2x00dev->default_ant.tx == 1) + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); + + if (rt2x00dev->default_ant.rx == 1) { + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1); + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); + } else if (rt2x00dev->default_ant.rx == 2) + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); + + if (rf->channel > 14) { + /* + * When TX power is below 0, we should increase it by 7 to + * make it a positive value (Minumum value is -7). + * However this means that values between 0 and 7 have + * double meaning, and we should set a 7DBm boost flag. + */ + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, + (info->tx_power1 >= 0)); + + if (info->tx_power1 < 0) + info->tx_power1 += 7; + + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, + TXPOWER_A_TO_DEV(info->tx_power1)); + + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, + (info->tx_power2 >= 0)); + + if (info->tx_power2 < 0) + info->tx_power2 += 7; + + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, + TXPOWER_A_TO_DEV(info->tx_power2)); + } else { + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, + TXPOWER_G_TO_DEV(info->tx_power1)); + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, + TXPOWER_G_TO_DEV(info->tx_power2)); + } + + rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); + + rt2800pci_rf_write(rt2x00dev, 1, rf->rf1); + rt2800pci_rf_write(rt2x00dev, 2, rf->rf2); + rt2800pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); + rt2800pci_rf_write(rt2x00dev, 4, rf->rf4); + + udelay(200); + + rt2800pci_rf_write(rt2x00dev, 1, rf->rf1); + rt2800pci_rf_write(rt2x00dev, 2, rf->rf2); + rt2800pci_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); + rt2800pci_rf_write(rt2x00dev, 4, rf->rf4); + + udelay(200); + + rt2800pci_rf_write(rt2x00dev, 1, rf->rf1); + rt2800pci_rf_write(rt2x00dev, 2, rf->rf2); + rt2800pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); + rt2800pci_rf_write(rt2x00dev, 4, rf->rf4); +} + +static void rt2800pci_config_channel_rt3x(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + u8 rfcsr; + + rt2800pci_rfcsr_write(rt2x00dev, 2, rf->rf1); + rt2800pci_rfcsr_write(rt2x00dev, 2, rf->rf3); + + rt2800pci_rfcsr_read(rt2x00dev, 6, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2); + rt2800pci_rfcsr_write(rt2x00dev, 6, rfcsr); + + rt2800pci_rfcsr_read(rt2x00dev, 12, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, + TXPOWER_G_TO_DEV(info->tx_power1)); + rt2800pci_rfcsr_write(rt2x00dev, 12, rfcsr); + + rt2800pci_rfcsr_read(rt2x00dev, 23, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); + rt2800pci_rfcsr_write(rt2x00dev, 23, rfcsr); + + rt2800pci_rfcsr_write(rt2x00dev, 24, + rt2x00dev->calibration[conf_is_ht40(conf)]); + + rt2800pci_rfcsr_read(rt2x00dev, 23, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); + rt2800pci_rfcsr_write(rt2x00dev, 23, rfcsr); +} + +static void rt2800pci_config_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + u32 reg; + unsigned int tx_pin; + u8 bbp; + + if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) + rt2800pci_config_channel_rt2x(rt2x00dev, conf, rf, info); + else + rt2800pci_config_channel_rt3x(rt2x00dev, conf, rf, info); + + /* + * Change BBP settings + */ + rt2800pci_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); + rt2800pci_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); + rt2800pci_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); + rt2800pci_bbp_write(rt2x00dev, 86, 0); + + if (rf->channel <= 14) { + if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { + rt2800pci_bbp_write(rt2x00dev, 82, 0x62); + rt2800pci_bbp_write(rt2x00dev, 75, 0x46); + } else { + rt2800pci_bbp_write(rt2x00dev, 82, 0x84); + rt2800pci_bbp_write(rt2x00dev, 75, 0x50); + } + } else { + rt2800pci_bbp_write(rt2x00dev, 82, 0xf2); + + if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) + rt2800pci_bbp_write(rt2x00dev, 75, 0x46); + else + rt2800pci_bbp_write(rt2x00dev, 75, 0x50); + } + + rt2x00pci_register_read(rt2x00dev, TX_BAND_CFG, ®); + rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); + rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14); + rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14); + rt2x00pci_register_write(rt2x00dev, TX_BAND_CFG, reg); + + tx_pin = 0; + + /* Turn on unused PA or LNA when not using 1T or 1R */ + if (rt2x00dev->default_ant.tx != 1) { + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); + } + + /* Turn on unused PA or LNA when not using 1T or 1R */ + if (rt2x00dev->default_ant.rx != 1) { + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); + } + + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14); + + rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); + + rt2800pci_bbp_read(rt2x00dev, 4, &bbp); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); + rt2800pci_bbp_write(rt2x00dev, 4, bbp); + + rt2800pci_bbp_read(rt2x00dev, 3, &bbp); + rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); + rt2800pci_bbp_write(rt2x00dev, 3, bbp); + + if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { + if (conf_is_ht40(conf)) { + rt2800pci_bbp_write(rt2x00dev, 69, 0x1a); + rt2800pci_bbp_write(rt2x00dev, 70, 0x0a); + rt2800pci_bbp_write(rt2x00dev, 73, 0x16); + } else { + rt2800pci_bbp_write(rt2x00dev, 69, 0x16); + rt2800pci_bbp_write(rt2x00dev, 70, 0x08); + rt2800pci_bbp_write(rt2x00dev, 73, 0x11); + } + } + + msleep(1); +} + +static void rt2800pci_config_txpower(struct rt2x00_dev *rt2x00dev, + const int txpower) +{ + u32 reg; + u32 value = TXPOWER_G_TO_DEV(txpower); + u8 r1; + + rt2800pci_bbp_read(rt2x00dev, 1, &r1); + rt2x00_set_field8(®, BBP1_TX_POWER, 0); + rt2800pci_bbp_write(rt2x00dev, 1, r1); + + rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_0, ®); + rt2x00_set_field32(®, TX_PWR_CFG_0_1MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_2MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_55MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_11MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_6MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_9MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_12MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_18MBS, value); + rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_0, reg); + + rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_1, ®); + rt2x00_set_field32(®, TX_PWR_CFG_1_24MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_36MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_48MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_54MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS0, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS1, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS2, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS3, value); + rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_1, reg); + + rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_2, ®); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS4, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS5, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS6, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS7, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS8, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS9, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS10, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS11, value); + rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_2, reg); + + rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_3, ®); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS12, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS13, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS14, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS15, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN1, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN2, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN3, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN4, value); + rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_3, reg); + + rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_4, ®); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN5, value); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN6, value); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN7, value); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN8, value); + rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_4, reg); +} + +static void rt2800pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + u32 reg; + + rt2x00pci_register_read(rt2x00dev, TX_RTY_CFG, ®); + rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, + libconf->conf->short_frame_max_tx_count); + rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, + libconf->conf->long_frame_max_tx_count); + rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); + rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); + rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); + rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); + rt2x00pci_register_write(rt2x00dev, TX_RTY_CFG, reg); +} + +static void rt2800pci_config_ps(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + enum dev_state state = + (libconf->conf->flags & IEEE80211_CONF_PS) ? + STATE_SLEEP : STATE_AWAKE; + u32 reg; + + if (state == STATE_SLEEP) { + rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); + + rt2x00pci_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, + libconf->conf->listen_interval - 1); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1); + rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); + + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); + } else { + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); + + rt2x00pci_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); + rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); + } +} + +static void rt2800pci_config(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf, + const unsigned int flags) +{ + /* Always recalculate LNA gain before changing configuration */ + rt2800pci_config_lna_gain(rt2x00dev, libconf); + + if (flags & IEEE80211_CONF_CHANGE_CHANNEL) + rt2800pci_config_channel(rt2x00dev, libconf->conf, + &libconf->rf, &libconf->channel); + if (flags & IEEE80211_CONF_CHANGE_POWER) + rt2800pci_config_txpower(rt2x00dev, libconf->conf->power_level); + if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) + rt2800pci_config_retry_limit(rt2x00dev, libconf); + if (flags & IEEE80211_CONF_CHANGE_PS) + rt2800pci_config_ps(rt2x00dev, libconf); +} + +/* + * Link tuning + */ +static void rt2800pci_link_stats(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) +{ + u32 reg; + + /* + * Update FCS error count from register. + */ + rt2x00pci_register_read(rt2x00dev, RX_STA_CNT0, ®); + qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR); +} + +static u8 rt2800pci_get_default_vgc(struct rt2x00_dev *rt2x00dev) +{ + if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) + return 0x2e + rt2x00dev->lna_gain; + + if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) + return 0x32 + (rt2x00dev->lna_gain * 5) / 3; + else + return 0x3a + (rt2x00dev->lna_gain * 5) / 3; +} + +static inline void rt2800pci_set_vgc(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, u8 vgc_level) +{ + if (qual->vgc_level != vgc_level) { + rt2800pci_bbp_write(rt2x00dev, 66, vgc_level); + qual->vgc_level = vgc_level; + qual->vgc_level_reg = vgc_level; + } +} + +static void rt2800pci_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) +{ + rt2800pci_set_vgc(rt2x00dev, qual, + rt2800pci_get_default_vgc(rt2x00dev)); +} + +static void rt2800pci_link_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count) +{ + if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) + return; + + /* + * When RSSI is better then -80 increase VGC level with 0x10 + */ + rt2800pci_set_vgc(rt2x00dev, qual, + rt2800pci_get_default_vgc(rt2x00dev) + + ((qual->rssi > -80) * 0x10)); +} + /* * Firmware functions */ @@ -244,7 +1257,7 @@ static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev, * Wait for stable hardware. */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, MAC_CSR0, ®); + rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); if (reg && reg != ~0) break; msleep(1); @@ -255,42 +1268,42 @@ static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev, return -EBUSY; } - rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002); - rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000); + rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002); + rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000); /* * Disable DMA, will be reenabled later when enabling * the radio. */ - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); - rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); /* * enable Host program ram write selection */ reg = 0; rt2x00_set_field32(®, PBF_SYS_CTRL_HOST_RAM_WRITE, 1); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg); + rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg); /* * Write firmware to device. */ - rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, + rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, data, len); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); + rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); + rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); /* * Wait for device to stabilize. */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); + rt2x00pci_register_read(rt2x00dev, PBF_SYS_CTRL, ®); if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) break; msleep(1); @@ -309,8 +1322,8 @@ static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev, /* * Initialize BBP R/W access agent */ - rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); return 0; } @@ -360,7 +1373,7 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) struct queue_entry_priv_pci *entry_priv; u32 reg; - rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); + rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); @@ -368,54 +1381,539 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); - rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); + rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); + rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); + rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); /* * Initialize registers. */ entry_priv = rt2x00dev->tx[0].entries[0].priv_data; - rt2800_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma); - rt2800_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit); - rt2800_register_write(rt2x00dev, TX_CTX_IDX0, 0); - rt2800_register_write(rt2x00dev, TX_DTX_IDX0, 0); + rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma); + rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit); + rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0); + rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX0, 0); entry_priv = rt2x00dev->tx[1].entries[0].priv_data; - rt2800_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma); - rt2800_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit); - rt2800_register_write(rt2x00dev, TX_CTX_IDX1, 0); - rt2800_register_write(rt2x00dev, TX_DTX_IDX1, 0); + rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma); + rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit); + rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0); + rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX1, 0); entry_priv = rt2x00dev->tx[2].entries[0].priv_data; - rt2800_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma); - rt2800_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit); - rt2800_register_write(rt2x00dev, TX_CTX_IDX2, 0); - rt2800_register_write(rt2x00dev, TX_DTX_IDX2, 0); + rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma); + rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit); + rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0); + rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX2, 0); entry_priv = rt2x00dev->tx[3].entries[0].priv_data; - rt2800_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma); - rt2800_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit); - rt2800_register_write(rt2x00dev, TX_CTX_IDX3, 0); - rt2800_register_write(rt2x00dev, TX_DTX_IDX3, 0); + rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma); + rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit); + rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0); + rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0); entry_priv = rt2x00dev->rx->entries[0].priv_data; - rt2800_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); - rt2800_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit); - rt2800_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1); - rt2800_register_write(rt2x00dev, RX_DRX_IDX, 0); + rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); + rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit); + rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1); + rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0); /* * Enable global DMA configuration */ - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); - rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + + rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0); + + return 0; +} + +static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + unsigned int i; + + rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); + + rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); + rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + + rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + + rt2x00pci_register_read(rt2x00dev, BCN_OFFSET0, ®); + rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ + rt2x00_set_field32(®, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */ + rt2x00_set_field32(®, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */ + rt2x00_set_field32(®, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */ + rt2x00pci_register_write(rt2x00dev, BCN_OFFSET0, reg); + + rt2x00pci_register_read(rt2x00dev, BCN_OFFSET1, ®); + rt2x00_set_field32(®, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */ + rt2x00_set_field32(®, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */ + rt2x00_set_field32(®, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */ + rt2x00_set_field32(®, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */ + rt2x00pci_register_write(rt2x00dev, BCN_OFFSET1, reg); + + rt2x00pci_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); + rt2x00pci_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); + + rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + + rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); + rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); + + rt2x00pci_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); + rt2x00pci_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); + + rt2x00pci_register_read(rt2x00dev, TX_LINK_CFG, ®); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32); + rt2x00_set_field32(®, TX_LINK_CFG_MFB_ENABLE, 0); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0); + rt2x00_set_field32(®, TX_LINK_CFG_TX_MRQ_EN, 0); + rt2x00_set_field32(®, TX_LINK_CFG_TX_RDG_EN, 0); + rt2x00_set_field32(®, TX_LINK_CFG_TX_CF_ACK_EN, 1); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB, 0); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFS, 0); + rt2x00pci_register_write(rt2x00dev, TX_LINK_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10); + rt2x00pci_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, MAX_LEN_CFG, ®); + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); + if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION && + rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION) + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); + else + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); + rt2x00_set_field32(®, MAX_LEN_CFG_MIN_PSDU, 0); + rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0); + rt2x00pci_register_write(rt2x00dev, MAX_LEN_CFG, reg); + + rt2x00pci_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f); + + rt2x00pci_register_read(rt2x00dev, AUTO_RSP_CFG, ®); + rt2x00_set_field32(®, AUTO_RSP_CFG_AUTORESPONDER, 1); + rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MMODE, 0); + rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MREF, 0); + rt2x00_set_field32(®, AUTO_RSP_CFG_DUAL_CTS_EN, 0); + rt2x00_set_field32(®, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0); + rt2x00pci_register_write(rt2x00dev, AUTO_RSP_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, CCK_PROT_CFG, ®); + rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 8); + rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00pci_register_write(rt2x00dev, CCK_PROT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, OFDM_PROT_CFG, ®); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 8); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00pci_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, MM20_PROT_CFG, ®); + rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_RATE, 0x4004); + rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0); + rt2x00pci_register_write(rt2x00dev, MM20_PROT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, MM40_PROT_CFG, ®); + rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084); + rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00pci_register_write(rt2x00dev, MM40_PROT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, GF20_PROT_CFG, ®); + rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_RATE, 0x4004); + rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0); + rt2x00pci_register_write(rt2x00dev, GF20_PROT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, GF40_PROT_CFG, ®); + rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_RATE, 0x4084); + rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00pci_register_write(rt2x00dev, GF40_PROT_CFG, reg); + + rt2x00pci_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f); + rt2x00pci_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); + + rt2x00pci_register_read(rt2x00dev, TX_RTS_CFG, ®); + rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, + IEEE80211_MAX_RTS_THRESHOLD); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 0); + rt2x00pci_register_write(rt2x00dev, TX_RTS_CFG, reg); + + rt2x00pci_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); + rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); + + /* + * ASIC will keep garbage value after boot, clear encryption keys. + */ + for (i = 0; i < 4; i++) + rt2x00pci_register_write(rt2x00dev, + SHARED_KEY_MODE_ENTRY(i), 0); + + for (i = 0; i < 256; i++) { + u32 wcid[2] = { 0xffffffff, 0x00ffffff }; + rt2x00pci_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), + wcid, sizeof(wcid)); + + rt2x00pci_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); + rt2x00pci_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); + } + + /* + * Clear all beacons + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE4, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE5, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE6, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE7, 0); + + rt2x00pci_register_read(rt2x00dev, HT_FBK_CFG0, ®); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS0FBK, 0); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS1FBK, 0); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS2FBK, 1); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS3FBK, 2); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS4FBK, 3); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS5FBK, 4); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS6FBK, 5); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS7FBK, 6); + rt2x00pci_register_write(rt2x00dev, HT_FBK_CFG0, reg); + + rt2x00pci_register_read(rt2x00dev, HT_FBK_CFG1, ®); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS8FBK, 8); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS9FBK, 8); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS10FBK, 9); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS11FBK, 10); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS12FBK, 11); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS13FBK, 12); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS14FBK, 13); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS15FBK, 14); + rt2x00pci_register_write(rt2x00dev, HT_FBK_CFG1, reg); + + rt2x00pci_register_read(rt2x00dev, LG_FBK_CFG0, ®); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 9); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 10); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 11); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 12); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS6FBK, 13); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS7FBK, 14); + rt2x00pci_register_write(rt2x00dev, LG_FBK_CFG0, reg); + + rt2x00pci_register_read(rt2x00dev, LG_FBK_CFG1, ®); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS0FBK, 0); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS1FBK, 0); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS2FBK, 1); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS3FBK, 2); + rt2x00pci_register_write(rt2x00dev, LG_FBK_CFG1, reg); + + /* + * We must clear the error counters. + * These registers are cleared on read, + * so we may pass a useless variable to store the value. + */ + rt2x00pci_register_read(rt2x00dev, RX_STA_CNT0, ®); + rt2x00pci_register_read(rt2x00dev, RX_STA_CNT1, ®); + rt2x00pci_register_read(rt2x00dev, RX_STA_CNT2, ®); + rt2x00pci_register_read(rt2x00dev, TX_STA_CNT0, ®); + rt2x00pci_register_read(rt2x00dev, TX_STA_CNT1, ®); + rt2x00pci_register_read(rt2x00dev, TX_STA_CNT2, ®); + + return 0; +} + +static int rt2800pci_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u32 reg; + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00pci_register_read(rt2x00dev, MAC_STATUS_CFG, ®); + if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY)) + return 0; + + udelay(REGISTER_BUSY_DELAY); + } + + ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n"); + return -EACCES; +} + +static int rt2800pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u8 value; + + /* + * BBP was enabled after firmware was loaded, + * but we need to reactivate it now. + */ + rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + msleep(1); + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2800pci_bbp_read(rt2x00dev, 0, &value); + if ((value != 0xff) && (value != 0x00)) + return 0; + udelay(REGISTER_BUSY_DELAY); + } + + ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); + return -EACCES; +} + +static int rt2800pci_init_bbp(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u16 eeprom; + u8 reg_id; + u8 value; + + if (unlikely(rt2800pci_wait_bbp_rf_ready(rt2x00dev) || + rt2800pci_wait_bbp_ready(rt2x00dev))) + return -EACCES; + + rt2800pci_bbp_write(rt2x00dev, 65, 0x2c); + rt2800pci_bbp_write(rt2x00dev, 66, 0x38); + rt2800pci_bbp_write(rt2x00dev, 69, 0x12); + rt2800pci_bbp_write(rt2x00dev, 70, 0x0a); + rt2800pci_bbp_write(rt2x00dev, 73, 0x10); + rt2800pci_bbp_write(rt2x00dev, 81, 0x37); + rt2800pci_bbp_write(rt2x00dev, 82, 0x62); + rt2800pci_bbp_write(rt2x00dev, 83, 0x6a); + rt2800pci_bbp_write(rt2x00dev, 84, 0x99); + rt2800pci_bbp_write(rt2x00dev, 86, 0x00); + rt2800pci_bbp_write(rt2x00dev, 91, 0x04); + rt2800pci_bbp_write(rt2x00dev, 92, 0x00); + rt2800pci_bbp_write(rt2x00dev, 103, 0x00); + rt2800pci_bbp_write(rt2x00dev, 105, 0x05); + + if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { + rt2800pci_bbp_write(rt2x00dev, 69, 0x16); + rt2800pci_bbp_write(rt2x00dev, 73, 0x12); + } + + if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) + rt2800pci_bbp_write(rt2x00dev, 84, 0x19); + + if (rt2x00_rt(&rt2x00dev->chip, RT3052)) { + rt2800pci_bbp_write(rt2x00dev, 31, 0x08); + rt2800pci_bbp_write(rt2x00dev, 78, 0x0e); + rt2800pci_bbp_write(rt2x00dev, 80, 0x08); + } + + for (i = 0; i < EEPROM_BBP_SIZE; i++) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); + + if (eeprom != 0xffff && eeprom != 0x0000) { + reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); + value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); + rt2800pci_bbp_write(rt2x00dev, reg_id, value); + } + } - rt2800_register_write(rt2x00dev, DELAY_INT_CFG, 0); + return 0; +} + +static u8 rt2800pci_init_rx_filter(struct rt2x00_dev *rt2x00dev, + bool bw40, u8 rfcsr24, u8 filter_target) +{ + unsigned int i; + u8 bbp; + u8 rfcsr; + u8 passband; + u8 stopband; + u8 overtuned = 0; + + rt2800pci_rfcsr_write(rt2x00dev, 24, rfcsr24); + + rt2800pci_bbp_read(rt2x00dev, 4, &bbp); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40); + rt2800pci_bbp_write(rt2x00dev, 4, bbp); + + rt2800pci_rfcsr_read(rt2x00dev, 22, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1); + rt2800pci_rfcsr_write(rt2x00dev, 22, rfcsr); + + /* + * Set power & frequency of passband test tone + */ + rt2800pci_bbp_write(rt2x00dev, 24, 0); + + for (i = 0; i < 100; i++) { + rt2800pci_bbp_write(rt2x00dev, 25, 0x90); + msleep(1); + + rt2800pci_bbp_read(rt2x00dev, 55, &passband); + if (passband) + break; + } + + /* + * Set power & frequency of stopband test tone + */ + rt2800pci_bbp_write(rt2x00dev, 24, 0x06); + + for (i = 0; i < 100; i++) { + rt2800pci_bbp_write(rt2x00dev, 25, 0x90); + msleep(1); + + rt2800pci_bbp_read(rt2x00dev, 55, &stopband); + + if ((passband - stopband) <= filter_target) { + rfcsr24++; + overtuned += ((passband - stopband) == filter_target); + } else + break; + + rt2800pci_rfcsr_write(rt2x00dev, 24, rfcsr24); + } + + rfcsr24 -= !!overtuned; + + rt2800pci_rfcsr_write(rt2x00dev, 24, rfcsr24); + return rfcsr24; +} + +static int rt2800pci_init_rfcsr(struct rt2x00_dev *rt2x00dev) +{ + u8 rfcsr; + u8 bbp; + + if (!rt2x00_rf(&rt2x00dev->chip, RF3020) && + !rt2x00_rf(&rt2x00dev->chip, RF3021) && + !rt2x00_rf(&rt2x00dev->chip, RF3022)) + return 0; + + /* + * Init RF calibration. + */ + rt2800pci_rfcsr_read(rt2x00dev, 30, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); + rt2800pci_rfcsr_write(rt2x00dev, 30, rfcsr); + msleep(1); + rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); + rt2800pci_rfcsr_write(rt2x00dev, 30, rfcsr); + + rt2800pci_rfcsr_write(rt2x00dev, 0, 0x50); + rt2800pci_rfcsr_write(rt2x00dev, 1, 0x01); + rt2800pci_rfcsr_write(rt2x00dev, 2, 0xf7); + rt2800pci_rfcsr_write(rt2x00dev, 3, 0x75); + rt2800pci_rfcsr_write(rt2x00dev, 4, 0x40); + rt2800pci_rfcsr_write(rt2x00dev, 5, 0x03); + rt2800pci_rfcsr_write(rt2x00dev, 6, 0x02); + rt2800pci_rfcsr_write(rt2x00dev, 7, 0x50); + rt2800pci_rfcsr_write(rt2x00dev, 8, 0x39); + rt2800pci_rfcsr_write(rt2x00dev, 9, 0x0f); + rt2800pci_rfcsr_write(rt2x00dev, 10, 0x60); + rt2800pci_rfcsr_write(rt2x00dev, 11, 0x21); + rt2800pci_rfcsr_write(rt2x00dev, 12, 0x75); + rt2800pci_rfcsr_write(rt2x00dev, 13, 0x75); + rt2800pci_rfcsr_write(rt2x00dev, 14, 0x90); + rt2800pci_rfcsr_write(rt2x00dev, 15, 0x58); + rt2800pci_rfcsr_write(rt2x00dev, 16, 0xb3); + rt2800pci_rfcsr_write(rt2x00dev, 17, 0x92); + rt2800pci_rfcsr_write(rt2x00dev, 18, 0x2c); + rt2800pci_rfcsr_write(rt2x00dev, 19, 0x02); + rt2800pci_rfcsr_write(rt2x00dev, 20, 0xba); + rt2800pci_rfcsr_write(rt2x00dev, 21, 0xdb); + rt2800pci_rfcsr_write(rt2x00dev, 22, 0x00); + rt2800pci_rfcsr_write(rt2x00dev, 23, 0x31); + rt2800pci_rfcsr_write(rt2x00dev, 24, 0x08); + rt2800pci_rfcsr_write(rt2x00dev, 25, 0x01); + rt2800pci_rfcsr_write(rt2x00dev, 26, 0x25); + rt2800pci_rfcsr_write(rt2x00dev, 27, 0x23); + rt2800pci_rfcsr_write(rt2x00dev, 28, 0x13); + rt2800pci_rfcsr_write(rt2x00dev, 29, 0x83); + + /* + * Set RX Filter calibration for 20MHz and 40MHz + */ + rt2x00dev->calibration[0] = + rt2800pci_init_rx_filter(rt2x00dev, false, 0x07, 0x16); + rt2x00dev->calibration[1] = + rt2800pci_init_rx_filter(rt2x00dev, true, 0x27, 0x19); + + /* + * Set back to initial state + */ + rt2800pci_bbp_write(rt2x00dev, 24, 0); + + rt2800pci_rfcsr_read(rt2x00dev, 22, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0); + rt2800pci_rfcsr_write(rt2x00dev, 22, rfcsr); + + /* + * set BBP back to BW20 + */ + rt2800pci_bbp_read(rt2x00dev, 4, &bbp); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0); + rt2800pci_bbp_write(rt2x00dev, 4, bbp); return 0; } @@ -428,11 +1926,11 @@ static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev, { u32 reg; - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, (state == STATE_RADIO_RX_ON) || (state == STATE_RADIO_RX_ON_LINK)); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); } static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, @@ -446,11 +1944,11 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, * should clear the register to assure a clean state. */ if (state == STATE_RADIO_IRQ_ON) { - rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); - rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); + rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); + rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); } - rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); + rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, mask); rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, mask); rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, mask); @@ -469,7 +1967,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, INT_MASK_CSR_GPTIMER, mask); rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, mask); rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, mask); - rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); + rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); } static int rt2800pci_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) @@ -478,7 +1976,7 @@ static int rt2800pci_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) u32 reg; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) return 0; @@ -500,50 +1998,50 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) */ if (unlikely(rt2800pci_wait_wpdma_ready(rt2x00dev) || rt2800pci_init_queues(rt2x00dev) || - rt2800_init_registers(rt2x00dev) || + rt2800pci_init_registers(rt2x00dev) || rt2800pci_wait_wpdma_ready(rt2x00dev) || - rt2800_init_bbp(rt2x00dev) || - rt2800_init_rfcsr(rt2x00dev))) + rt2800pci_init_bbp(rt2x00dev) || + rt2800pci_init_rfcsr(rt2x00dev))) return -EIO; /* * Send signal to firmware during boot time. */ - rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); + rt2800pci_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); /* * Enable RX. */ - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1); rt2x00_set_field32(®, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2); rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); - rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); /* * Initialize LED control */ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff, + rt2800pci_mcu_request(rt2x00dev, MCU_LED_1, 0xff, word & 0xff, (word >> 8) & 0xff); rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff, + rt2800pci_mcu_request(rt2x00dev, MCU_LED_2, 0xff, word & 0xff, (word >> 8) & 0xff); rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff, + rt2800pci_mcu_request(rt2x00dev, MCU_LED_3, 0xff, word & 0xff, (word >> 8) & 0xff); return 0; @@ -553,21 +2051,21 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) { u32 reg; - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); - rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0); - rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0); - rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0); + rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0); + rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0); + rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280); + rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280); - rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); + rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); @@ -575,10 +2073,10 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); - rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); + rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); - rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); + rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); + rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); /* Wait for DMA, ignore error */ rt2800pci_wait_wpdma_ready(rt2x00dev); @@ -592,10 +2090,10 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, * if the device is booting and wasn't asleep it will return * failure when attempting to wakeup. */ - rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); + rt2800pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); if (state == STATE_AWAKE) { - rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0); + rt2800pci_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0); rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP); } @@ -697,7 +2195,7 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? - txdesc->key_idx : 0xff); + (skbdesc->entry->entry_idx + 1) : 0xff); rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, skb->len - txdesc->l2pad); rt2x00_set_field32(&word, TXWI_W1_PACKETID, @@ -706,8 +2204,8 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * Always write 0 to IV/EIV fields, hardware will insert the IV - * from the IVEIV register when TXD_W3_WIV is set to 0. - * When TXD_W3_WIV is set to 1 it will use the IV data + * from the IVEIV register when ENTRY_TXD_ENCRYPT_IV is set to 0. + * When ENTRY_TXD_ENCRYPT_IV is set to 1 it will use the IV data * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which * crypto entry in the registers should be used to encrypt the frame. */ @@ -767,18 +2265,18 @@ static void rt2800pci_write_beacon(struct queue_entry *entry) * Disable beaconing while we are reloading the beacon data, * otherwise we might be sending out invalid data. */ - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); /* * Write entire beacon with descriptor to register. */ beacon_base = HW_BEACON_OFFSET(entry->entry_idx); - rt2800_register_multiwrite(rt2x00dev, + rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, skbdesc->desc, skbdesc->desc_len); - rt2800_register_multiwrite(rt2x00dev, + rt2x00pci_register_multiwrite(rt2x00dev, beacon_base + skbdesc->desc_len, entry->skb->data, entry->skb->len); @@ -797,12 +2295,12 @@ static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, u32 reg; if (queue_idx == QID_BEACON) { - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) { rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); } return; } @@ -818,7 +2316,7 @@ static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, else qidx = queue_idx; - rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), idx); + rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(qidx), idx); } static void rt2800pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, @@ -827,16 +2325,16 @@ static void rt2800pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, u32 reg; if (qid == QID_BEACON) { - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, 0); + rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, 0); return; } - rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); + rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, (qid == QID_AC_BE)); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, (qid == QID_AC_BK)); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, (qid == QID_AC_VI)); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, (qid == QID_AC_VO)); - rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); + rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg); } /* @@ -932,7 +2430,7 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, * Set RX IDX in register to inform hardware that we have handled * this entry and it is available for reuse again. */ - rt2800_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx); + rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx); /* * Remove TXWI descriptor from start of buffer. @@ -969,7 +2467,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) old_reg = 0; while (1) { - rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); + rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, ®); if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) break; @@ -1053,8 +2551,8 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) u32 reg; /* Read status and ACK all interrupts */ - rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); - rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); + rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); + rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); if (!reg) return IRQ_NONE; @@ -1211,7 +2709,7 @@ static int rt2800pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * Identify RF chipset. */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); - rt2800_register_read(rt2x00dev, MAC_CSR0, ®); + rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip_rf(rt2x00dev, value, reg); if (!rt2x00_rf(&rt2x00dev->chip, RF2820) && @@ -1260,9 +2758,9 @@ static int rt2800pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * Store led settings, for correct led behaviour. */ #ifdef CONFIG_RT2X00_LIB_LEDS - rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); - rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); + rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); + rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); + rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg); #endif /* CONFIG_RT2X00_LIB_LEDS */ @@ -1450,25 +2948,10 @@ static int rt2800pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) return 0; } -static const struct rt2800_ops rt2800pci_rt2800_ops = { - .register_read = rt2x00pci_register_read, - .register_write = rt2x00pci_register_write, - .register_write_lock = rt2x00pci_register_write, /* same for PCI */ - - .register_multiread = rt2x00pci_register_multiread, - .register_multiwrite = rt2x00pci_register_multiwrite, - - .regbusy_read = rt2x00pci_regbusy_read, -}; - static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; - rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); - - rt2x00dev->priv = (void *)&rt2800pci_rt2800_ops; - /* * Allocate eeprom data. */ @@ -1513,6 +2996,161 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) return 0; } +/* + * IEEE80211 stack callback functions. + */ +static void rt2800pci_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, + u32 *iv32, u16 *iv16) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct mac_iveiv_entry iveiv_entry; + u32 offset; + + offset = MAC_IVEIV_ENTRY(hw_key_idx); + rt2x00pci_register_multiread(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); + + memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16)); + memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32)); +} + +static int rt2800pci_set_rts_threshold(struct ieee80211_hw *hw, u32 value) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + u32 reg; + bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD); + + rt2x00pci_register_read(rt2x00dev, TX_RTS_CFG, ®); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, value); + rt2x00pci_register_write(rt2x00dev, TX_RTS_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, CCK_PROT_CFG, ®); + rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, enabled); + rt2x00pci_register_write(rt2x00dev, CCK_PROT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, OFDM_PROT_CFG, ®); + rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, enabled); + rt2x00pci_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, MM20_PROT_CFG, ®); + rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, enabled); + rt2x00pci_register_write(rt2x00dev, MM20_PROT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, MM40_PROT_CFG, ®); + rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, enabled); + rt2x00pci_register_write(rt2x00dev, MM40_PROT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, GF20_PROT_CFG, ®); + rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, enabled); + rt2x00pci_register_write(rt2x00dev, GF20_PROT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, GF40_PROT_CFG, ®); + rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, enabled); + rt2x00pci_register_write(rt2x00dev, GF40_PROT_CFG, reg); + + return 0; +} + +static int rt2800pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, + const struct ieee80211_tx_queue_params *params) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct data_queue *queue; + struct rt2x00_field32 field; + int retval; + u32 reg; + u32 offset; + + /* + * First pass the configuration through rt2x00lib, that will + * update the queue settings and validate the input. After that + * we are free to update the registers based on the value + * in the queue parameter. + */ + retval = rt2x00mac_conf_tx(hw, queue_idx, params); + if (retval) + return retval; + + /* + * We only need to perform additional register initialization + * for WMM queues/ + */ + if (queue_idx >= 4) + return 0; + + queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); + + /* Update WMM TXOP register */ + offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2))); + field.bit_offset = (queue_idx & 1) * 16; + field.bit_mask = 0xffff << field.bit_offset; + + rt2x00pci_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, field, queue->txop); + rt2x00pci_register_write(rt2x00dev, offset, reg); + + /* Update WMM registers */ + field.bit_offset = queue_idx * 4; + field.bit_mask = 0xf << field.bit_offset; + + rt2x00pci_register_read(rt2x00dev, WMM_AIFSN_CFG, ®); + rt2x00_set_field32(®, field, queue->aifs); + rt2x00pci_register_write(rt2x00dev, WMM_AIFSN_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, WMM_CWMIN_CFG, ®); + rt2x00_set_field32(®, field, queue->cw_min); + rt2x00pci_register_write(rt2x00dev, WMM_CWMIN_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, WMM_CWMAX_CFG, ®); + rt2x00_set_field32(®, field, queue->cw_max); + rt2x00pci_register_write(rt2x00dev, WMM_CWMAX_CFG, reg); + + /* Update EDCA registers */ + offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx); + + rt2x00pci_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, EDCA_AC0_CFG_TX_OP, queue->txop); + rt2x00_set_field32(®, EDCA_AC0_CFG_AIFSN, queue->aifs); + rt2x00_set_field32(®, EDCA_AC0_CFG_CWMIN, queue->cw_min); + rt2x00_set_field32(®, EDCA_AC0_CFG_CWMAX, queue->cw_max); + rt2x00pci_register_write(rt2x00dev, offset, reg); + + return 0; +} + +static u64 rt2800pci_get_tsf(struct ieee80211_hw *hw) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + u64 tsf; + u32 reg; + + rt2x00pci_register_read(rt2x00dev, TSF_TIMER_DW1, ®); + tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32; + rt2x00pci_register_read(rt2x00dev, TSF_TIMER_DW0, ®); + tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD); + + return tsf; +} + +static const struct ieee80211_ops rt2800pci_mac80211_ops = { + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, + .remove_interface = rt2x00mac_remove_interface, + .config = rt2x00mac_config, + .configure_filter = rt2x00mac_configure_filter, + .set_key = rt2x00mac_set_key, + .get_stats = rt2x00mac_get_stats, + .get_tkip_seq = rt2800pci_get_tkip_seq, + .set_rts_threshold = rt2800pci_set_rts_threshold, + .bss_info_changed = rt2x00mac_bss_info_changed, + .conf_tx = rt2800pci_conf_tx, + .get_tx_stats = rt2x00mac_get_tx_stats, + .get_tsf = rt2800pci_get_tsf, + .rfkill_poll = rt2x00mac_rfkill_poll, +}; + static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .irq_handler = rt2800pci_interrupt, .probe_hw = rt2800pci_probe_hw, @@ -1524,23 +3162,23 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .get_entry_state = rt2800pci_get_entry_state, .clear_entry = rt2800pci_clear_entry, .set_device_state = rt2800pci_set_device_state, - .rfkill_poll = rt2800_rfkill_poll, - .link_stats = rt2800_link_stats, - .reset_tuner = rt2800_reset_tuner, - .link_tuner = rt2800_link_tuner, + .rfkill_poll = rt2800pci_rfkill_poll, + .link_stats = rt2800pci_link_stats, + .reset_tuner = rt2800pci_reset_tuner, + .link_tuner = rt2800pci_link_tuner, .write_tx_desc = rt2800pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, .write_beacon = rt2800pci_write_beacon, .kick_tx_queue = rt2800pci_kick_tx_queue, .kill_tx_queue = rt2800pci_kill_tx_queue, .fill_rxdone = rt2800pci_fill_rxdone, - .config_shared_key = rt2800_config_shared_key, - .config_pairwise_key = rt2800_config_pairwise_key, - .config_filter = rt2800_config_filter, - .config_intf = rt2800_config_intf, - .config_erp = rt2800_config_erp, - .config_ant = rt2800_config_ant, - .config = rt2800_config, + .config_shared_key = rt2800pci_config_shared_key, + .config_pairwise_key = rt2800pci_config_pairwise_key, + .config_filter = rt2800pci_config_filter, + .config_intf = rt2800pci_config_intf, + .config_erp = rt2800pci_config_erp, + .config_ant = rt2800pci_config_ant, + .config = rt2800pci_config, }; static const struct data_queue_desc rt2800pci_queue_rx = { @@ -1575,9 +3213,9 @@ static const struct rt2x00_ops rt2800pci_ops = { .tx = &rt2800pci_queue_tx, .bcn = &rt2800pci_queue_bcn, .lib = &rt2800pci_rt2x00_ops, - .hw = &rt2800_mac80211_ops, + .hw = &rt2800pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2800_rt2x00debug, + .debugfs = &rt2800pci_rt2x00debug, #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800pci.h b/trunk/drivers/net/wireless/rt2x00/rt2800pci.h index 1dbf13270cda..856908815221 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800pci.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2800pci.h @@ -27,61 +27,1464 @@ #ifndef RT2800PCI_H #define RT2800PCI_H +/* + * RF chip defines. + * + * RF2820 2.4G 2T3R + * RF2850 2.4G/5G 2T3R + * RF2720 2.4G 1T2R + * RF2750 2.4G/5G 1T2R + * RF3020 2.4G 1T1R + * RF2020 2.4G B/G + * RF3021 2.4G 1T2R + * RF3022 2.4G 2T2R + * RF3052 2.4G 2T2R + */ +#define RF2820 0x0001 +#define RF2850 0x0002 +#define RF2720 0x0003 +#define RF2750 0x0004 +#define RF3020 0x0005 +#define RF2020 0x0006 +#define RF3021 0x0007 +#define RF3022 0x0008 +#define RF3052 0x0009 + +/* + * RT2860 version + */ +#define RT2860C_VERSION 0x28600100 +#define RT2860D_VERSION 0x28600101 +#define RT2880E_VERSION 0x28720200 +#define RT2883_VERSION 0x28830300 +#define RT3070_VERSION 0x30700200 + +/* + * Signal information. + * Default offset is required for RSSI <-> dBm conversion. + */ +#define DEFAULT_RSSI_OFFSET 120 /* FIXME */ + +/* + * Register layout information. + */ +#define CSR_REG_BASE 0x1000 +#define CSR_REG_SIZE 0x0800 +#define EEPROM_BASE 0x0000 +#define EEPROM_SIZE 0x0110 +#define BBP_BASE 0x0000 +#define BBP_SIZE 0x0080 +#define RF_BASE 0x0004 +#define RF_SIZE 0x0010 + +/* + * Number of TX queues. + */ +#define NUM_TX_QUEUES 4 + /* * PCI registers. */ /* - * E2PROM_CSR: EEPROM control register. - * RELOAD: Write 1 to reload eeprom content. - * TYPE: 0: 93c46, 1:93c66. - * LOAD_STATUS: 1:loading, 0:done. + * E2PROM_CSR: EEPROM control register. + * RELOAD: Write 1 to reload eeprom content. + * TYPE: 0: 93c46, 1:93c66. + * LOAD_STATUS: 1:loading, 0:done. + */ +#define E2PROM_CSR 0x0004 +#define E2PROM_CSR_DATA_CLOCK FIELD32(0x00000001) +#define E2PROM_CSR_CHIP_SELECT FIELD32(0x00000002) +#define E2PROM_CSR_DATA_IN FIELD32(0x00000004) +#define E2PROM_CSR_DATA_OUT FIELD32(0x00000008) +#define E2PROM_CSR_TYPE FIELD32(0x00000030) +#define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040) +#define E2PROM_CSR_RELOAD FIELD32(0x00000080) + +/* + * INT_SOURCE_CSR: Interrupt source register. + * Write one to clear corresponding bit. + * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c + */ +#define INT_SOURCE_CSR 0x0200 +#define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001) +#define INT_SOURCE_CSR_TXDELAYINT FIELD32(0x00000002) +#define INT_SOURCE_CSR_RX_DONE FIELD32(0x00000004) +#define INT_SOURCE_CSR_AC0_DMA_DONE FIELD32(0x00000008) +#define INT_SOURCE_CSR_AC1_DMA_DONE FIELD32(0x00000010) +#define INT_SOURCE_CSR_AC2_DMA_DONE FIELD32(0x00000020) +#define INT_SOURCE_CSR_AC3_DMA_DONE FIELD32(0x00000040) +#define INT_SOURCE_CSR_HCCA_DMA_DONE FIELD32(0x00000080) +#define INT_SOURCE_CSR_MGMT_DMA_DONE FIELD32(0x00000100) +#define INT_SOURCE_CSR_MCU_COMMAND FIELD32(0x00000200) +#define INT_SOURCE_CSR_RXTX_COHERENT FIELD32(0x00000400) +#define INT_SOURCE_CSR_TBTT FIELD32(0x00000800) +#define INT_SOURCE_CSR_PRE_TBTT FIELD32(0x00001000) +#define INT_SOURCE_CSR_TX_FIFO_STATUS FIELD32(0x00002000) +#define INT_SOURCE_CSR_AUTO_WAKEUP FIELD32(0x00004000) +#define INT_SOURCE_CSR_GPTIMER FIELD32(0x00008000) +#define INT_SOURCE_CSR_RX_COHERENT FIELD32(0x00010000) +#define INT_SOURCE_CSR_TX_COHERENT FIELD32(0x00020000) + +/* + * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF. + */ +#define INT_MASK_CSR 0x0204 +#define INT_MASK_CSR_RXDELAYINT FIELD32(0x00000001) +#define INT_MASK_CSR_TXDELAYINT FIELD32(0x00000002) +#define INT_MASK_CSR_RX_DONE FIELD32(0x00000004) +#define INT_MASK_CSR_AC0_DMA_DONE FIELD32(0x00000008) +#define INT_MASK_CSR_AC1_DMA_DONE FIELD32(0x00000010) +#define INT_MASK_CSR_AC2_DMA_DONE FIELD32(0x00000020) +#define INT_MASK_CSR_AC3_DMA_DONE FIELD32(0x00000040) +#define INT_MASK_CSR_HCCA_DMA_DONE FIELD32(0x00000080) +#define INT_MASK_CSR_MGMT_DMA_DONE FIELD32(0x00000100) +#define INT_MASK_CSR_MCU_COMMAND FIELD32(0x00000200) +#define INT_MASK_CSR_RXTX_COHERENT FIELD32(0x00000400) +#define INT_MASK_CSR_TBTT FIELD32(0x00000800) +#define INT_MASK_CSR_PRE_TBTT FIELD32(0x00001000) +#define INT_MASK_CSR_TX_FIFO_STATUS FIELD32(0x00002000) +#define INT_MASK_CSR_AUTO_WAKEUP FIELD32(0x00004000) +#define INT_MASK_CSR_GPTIMER FIELD32(0x00008000) +#define INT_MASK_CSR_RX_COHERENT FIELD32(0x00010000) +#define INT_MASK_CSR_TX_COHERENT FIELD32(0x00020000) + +/* + * WPDMA_GLO_CFG + */ +#define WPDMA_GLO_CFG 0x0208 +#define WPDMA_GLO_CFG_ENABLE_TX_DMA FIELD32(0x00000001) +#define WPDMA_GLO_CFG_TX_DMA_BUSY FIELD32(0x00000002) +#define WPDMA_GLO_CFG_ENABLE_RX_DMA FIELD32(0x00000004) +#define WPDMA_GLO_CFG_RX_DMA_BUSY FIELD32(0x00000008) +#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE FIELD32(0x00000030) +#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE FIELD32(0x00000040) +#define WPDMA_GLO_CFG_BIG_ENDIAN FIELD32(0x00000080) +#define WPDMA_GLO_CFG_RX_HDR_SCATTER FIELD32(0x0000ff00) +#define WPDMA_GLO_CFG_HDR_SEG_LEN FIELD32(0xffff0000) + +/* + * WPDMA_RST_IDX + */ +#define WPDMA_RST_IDX 0x020c +#define WPDMA_RST_IDX_DTX_IDX0 FIELD32(0x00000001) +#define WPDMA_RST_IDX_DTX_IDX1 FIELD32(0x00000002) +#define WPDMA_RST_IDX_DTX_IDX2 FIELD32(0x00000004) +#define WPDMA_RST_IDX_DTX_IDX3 FIELD32(0x00000008) +#define WPDMA_RST_IDX_DTX_IDX4 FIELD32(0x00000010) +#define WPDMA_RST_IDX_DTX_IDX5 FIELD32(0x00000020) +#define WPDMA_RST_IDX_DRX_IDX0 FIELD32(0x00010000) + +/* + * DELAY_INT_CFG + */ +#define DELAY_INT_CFG 0x0210 +#define DELAY_INT_CFG_RXMAX_PTIME FIELD32(0x000000ff) +#define DELAY_INT_CFG_RXMAX_PINT FIELD32(0x00007f00) +#define DELAY_INT_CFG_RXDLY_INT_EN FIELD32(0x00008000) +#define DELAY_INT_CFG_TXMAX_PTIME FIELD32(0x00ff0000) +#define DELAY_INT_CFG_TXMAX_PINT FIELD32(0x7f000000) +#define DELAY_INT_CFG_TXDLY_INT_EN FIELD32(0x80000000) + +/* + * WMM_AIFSN_CFG: Aifsn for each EDCA AC + * AIFSN0: AC_BE + * AIFSN1: AC_BK + * AIFSN1: AC_VI + * AIFSN1: AC_VO + */ +#define WMM_AIFSN_CFG 0x0214 +#define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f) +#define WMM_AIFSN_CFG_AIFSN1 FIELD32(0x000000f0) +#define WMM_AIFSN_CFG_AIFSN2 FIELD32(0x00000f00) +#define WMM_AIFSN_CFG_AIFSN3 FIELD32(0x0000f000) + +/* + * WMM_CWMIN_CSR: CWmin for each EDCA AC + * CWMIN0: AC_BE + * CWMIN1: AC_BK + * CWMIN1: AC_VI + * CWMIN1: AC_VO + */ +#define WMM_CWMIN_CFG 0x0218 +#define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f) +#define WMM_CWMIN_CFG_CWMIN1 FIELD32(0x000000f0) +#define WMM_CWMIN_CFG_CWMIN2 FIELD32(0x00000f00) +#define WMM_CWMIN_CFG_CWMIN3 FIELD32(0x0000f000) + +/* + * WMM_CWMAX_CSR: CWmax for each EDCA AC + * CWMAX0: AC_BE + * CWMAX1: AC_BK + * CWMAX1: AC_VI + * CWMAX1: AC_VO + */ +#define WMM_CWMAX_CFG 0x021c +#define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f) +#define WMM_CWMAX_CFG_CWMAX1 FIELD32(0x000000f0) +#define WMM_CWMAX_CFG_CWMAX2 FIELD32(0x00000f00) +#define WMM_CWMAX_CFG_CWMAX3 FIELD32(0x0000f000) + +/* + * AC_TXOP0: AC_BK/AC_BE TXOP register + * AC0TXOP: AC_BK in unit of 32us + * AC1TXOP: AC_BE in unit of 32us + */ +#define WMM_TXOP0_CFG 0x0220 +#define WMM_TXOP0_CFG_AC0TXOP FIELD32(0x0000ffff) +#define WMM_TXOP0_CFG_AC1TXOP FIELD32(0xffff0000) + +/* + * AC_TXOP1: AC_VO/AC_VI TXOP register + * AC2TXOP: AC_VI in unit of 32us + * AC3TXOP: AC_VO in unit of 32us + */ +#define WMM_TXOP1_CFG 0x0224 +#define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff) +#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000) + +/* + * GPIO_CTRL_CFG: + */ +#define GPIO_CTRL_CFG 0x0228 +#define GPIO_CTRL_CFG_BIT0 FIELD32(0x00000001) +#define GPIO_CTRL_CFG_BIT1 FIELD32(0x00000002) +#define GPIO_CTRL_CFG_BIT2 FIELD32(0x00000004) +#define GPIO_CTRL_CFG_BIT3 FIELD32(0x00000008) +#define GPIO_CTRL_CFG_BIT4 FIELD32(0x00000010) +#define GPIO_CTRL_CFG_BIT5 FIELD32(0x00000020) +#define GPIO_CTRL_CFG_BIT6 FIELD32(0x00000040) +#define GPIO_CTRL_CFG_BIT7 FIELD32(0x00000080) +#define GPIO_CTRL_CFG_BIT8 FIELD32(0x00000100) + +/* + * MCU_CMD_CFG + */ +#define MCU_CMD_CFG 0x022c + +/* + * AC_BK register offsets + */ +#define TX_BASE_PTR0 0x0230 +#define TX_MAX_CNT0 0x0234 +#define TX_CTX_IDX0 0x0238 +#define TX_DTX_IDX0 0x023c + +/* + * AC_BE register offsets + */ +#define TX_BASE_PTR1 0x0240 +#define TX_MAX_CNT1 0x0244 +#define TX_CTX_IDX1 0x0248 +#define TX_DTX_IDX1 0x024c + +/* + * AC_VI register offsets + */ +#define TX_BASE_PTR2 0x0250 +#define TX_MAX_CNT2 0x0254 +#define TX_CTX_IDX2 0x0258 +#define TX_DTX_IDX2 0x025c + +/* + * AC_VO register offsets + */ +#define TX_BASE_PTR3 0x0260 +#define TX_MAX_CNT3 0x0264 +#define TX_CTX_IDX3 0x0268 +#define TX_DTX_IDX3 0x026c + +/* + * HCCA register offsets + */ +#define TX_BASE_PTR4 0x0270 +#define TX_MAX_CNT4 0x0274 +#define TX_CTX_IDX4 0x0278 +#define TX_DTX_IDX4 0x027c + +/* + * MGMT register offsets + */ +#define TX_BASE_PTR5 0x0280 +#define TX_MAX_CNT5 0x0284 +#define TX_CTX_IDX5 0x0288 +#define TX_DTX_IDX5 0x028c + +/* + * Queue register offset macros + */ +#define TX_QUEUE_REG_OFFSET 0x10 +#define TX_BASE_PTR(__x) TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET) +#define TX_MAX_CNT(__x) TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET) +#define TX_CTX_IDX(__x) TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET) +#define TX_DTX_IDX(__x) TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET) + +/* + * RX register offsets + */ +#define RX_BASE_PTR 0x0290 +#define RX_MAX_CNT 0x0294 +#define RX_CRX_IDX 0x0298 +#define RX_DRX_IDX 0x029c + +/* + * PBF_SYS_CTRL + * HOST_RAM_WRITE: enable Host program ram write selection + */ +#define PBF_SYS_CTRL 0x0400 +#define PBF_SYS_CTRL_READY FIELD32(0x00000080) +#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) + +/* + * HOST-MCU shared memory + */ +#define HOST_CMD_CSR 0x0404 +#define HOST_CMD_CSR_HOST_COMMAND FIELD32(0x000000ff) + +/* + * PBF registers + * Most are for debug. Driver doesn't touch PBF register. + */ +#define PBF_CFG 0x0408 +#define PBF_MAX_PCNT 0x040c +#define PBF_CTRL 0x0410 +#define PBF_INT_STA 0x0414 +#define PBF_INT_ENA 0x0418 + +/* + * BCN_OFFSET0: + */ +#define BCN_OFFSET0 0x042c +#define BCN_OFFSET0_BCN0 FIELD32(0x000000ff) +#define BCN_OFFSET0_BCN1 FIELD32(0x0000ff00) +#define BCN_OFFSET0_BCN2 FIELD32(0x00ff0000) +#define BCN_OFFSET0_BCN3 FIELD32(0xff000000) + +/* + * BCN_OFFSET1: + */ +#define BCN_OFFSET1 0x0430 +#define BCN_OFFSET1_BCN4 FIELD32(0x000000ff) +#define BCN_OFFSET1_BCN5 FIELD32(0x0000ff00) +#define BCN_OFFSET1_BCN6 FIELD32(0x00ff0000) +#define BCN_OFFSET1_BCN7 FIELD32(0xff000000) + +/* + * PBF registers + * Most are for debug. Driver doesn't touch PBF register. + */ +#define TXRXQ_PCNT 0x0438 +#define PBF_DBG 0x043c + +/* + * RF registers + */ +#define RF_CSR_CFG 0x0500 +#define RF_CSR_CFG_DATA FIELD32(0x000000ff) +#define RF_CSR_CFG_REGNUM FIELD32(0x00001f00) +#define RF_CSR_CFG_WRITE FIELD32(0x00010000) +#define RF_CSR_CFG_BUSY FIELD32(0x00020000) + +/* + * EFUSE_CSR: RT3090 EEPROM + */ +#define EFUSE_CTRL 0x0580 +#define EFUSE_CTRL_ADDRESS_IN FIELD32(0x03fe0000) +#define EFUSE_CTRL_MODE FIELD32(0x000000c0) +#define EFUSE_CTRL_KICK FIELD32(0x40000000) + +/* + * EFUSE_DATA0 + */ +#define EFUSE_DATA0 0x0590 + +/* + * EFUSE_DATA1 + */ +#define EFUSE_DATA1 0x0594 + +/* + * EFUSE_DATA2 + */ +#define EFUSE_DATA2 0x0598 + +/* + * EFUSE_DATA3 + */ +#define EFUSE_DATA3 0x059c + +/* + * MAC Control/Status Registers(CSR). + * Some values are set in TU, whereas 1 TU == 1024 us. + */ + +/* + * MAC_CSR0: ASIC revision number. + * ASIC_REV: 0 + * ASIC_VER: 2860 + */ +#define MAC_CSR0 0x1000 +#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff) +#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000) + +/* + * MAC_SYS_CTRL: + */ +#define MAC_SYS_CTRL 0x1004 +#define MAC_SYS_CTRL_RESET_CSR FIELD32(0x00000001) +#define MAC_SYS_CTRL_RESET_BBP FIELD32(0x00000002) +#define MAC_SYS_CTRL_ENABLE_TX FIELD32(0x00000004) +#define MAC_SYS_CTRL_ENABLE_RX FIELD32(0x00000008) +#define MAC_SYS_CTRL_CONTINUOUS_TX FIELD32(0x00000010) +#define MAC_SYS_CTRL_LOOPBACK FIELD32(0x00000020) +#define MAC_SYS_CTRL_WLAN_HALT FIELD32(0x00000040) +#define MAC_SYS_CTRL_RX_TIMESTAMP FIELD32(0x00000080) + +/* + * MAC_ADDR_DW0: STA MAC register 0 + */ +#define MAC_ADDR_DW0 0x1008 +#define MAC_ADDR_DW0_BYTE0 FIELD32(0x000000ff) +#define MAC_ADDR_DW0_BYTE1 FIELD32(0x0000ff00) +#define MAC_ADDR_DW0_BYTE2 FIELD32(0x00ff0000) +#define MAC_ADDR_DW0_BYTE3 FIELD32(0xff000000) + +/* + * MAC_ADDR_DW1: STA MAC register 1 + * UNICAST_TO_ME_MASK: + * Used to mask off bits from byte 5 of the MAC address + * to determine the UNICAST_TO_ME bit for RX frames. + * The full mask is complemented by BSS_ID_MASK: + * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK + */ +#define MAC_ADDR_DW1 0x100c +#define MAC_ADDR_DW1_BYTE4 FIELD32(0x000000ff) +#define MAC_ADDR_DW1_BYTE5 FIELD32(0x0000ff00) +#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK FIELD32(0x00ff0000) + +/* + * MAC_BSSID_DW0: BSSID register 0 + */ +#define MAC_BSSID_DW0 0x1010 +#define MAC_BSSID_DW0_BYTE0 FIELD32(0x000000ff) +#define MAC_BSSID_DW0_BYTE1 FIELD32(0x0000ff00) +#define MAC_BSSID_DW0_BYTE2 FIELD32(0x00ff0000) +#define MAC_BSSID_DW0_BYTE3 FIELD32(0xff000000) + +/* + * MAC_BSSID_DW1: BSSID register 1 + * BSS_ID_MASK: + * 0: 1-BSSID mode (BSS index = 0) + * 1: 2-BSSID mode (BSS index: Byte5, bit 0) + * 2: 4-BSSID mode (BSS index: byte5, bit 0 - 1) + * 3: 8-BSSID mode (BSS index: byte5, bit 0 - 2) + * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the + * BSSID. This will make sure that those bits will be ignored + * when determining the MY_BSS of RX frames. + */ +#define MAC_BSSID_DW1 0x1014 +#define MAC_BSSID_DW1_BYTE4 FIELD32(0x000000ff) +#define MAC_BSSID_DW1_BYTE5 FIELD32(0x0000ff00) +#define MAC_BSSID_DW1_BSS_ID_MASK FIELD32(0x00030000) +#define MAC_BSSID_DW1_BSS_BCN_NUM FIELD32(0x001c0000) + +/* + * MAX_LEN_CFG: Maximum frame length register. + * MAX_MPDU: rt2860b max 16k bytes + * MAX_PSDU: Maximum PSDU length + * (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 + */ +#define MAX_LEN_CFG 0x1018 +#define MAX_LEN_CFG_MAX_MPDU FIELD32(0x00000fff) +#define MAX_LEN_CFG_MAX_PSDU FIELD32(0x00003000) +#define MAX_LEN_CFG_MIN_PSDU FIELD32(0x0000c000) +#define MAX_LEN_CFG_MIN_MPDU FIELD32(0x000f0000) + +/* + * BBP_CSR_CFG: BBP serial control register + * VALUE: Register value to program into BBP + * REG_NUM: Selected BBP register + * READ_CONTROL: 0 write BBP, 1 read BBP + * BUSY: ASIC is busy executing BBP commands + * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks + * BBP_RW_MODE: 0 serial, 1 paralell + */ +#define BBP_CSR_CFG 0x101c +#define BBP_CSR_CFG_VALUE FIELD32(0x000000ff) +#define BBP_CSR_CFG_REGNUM FIELD32(0x0000ff00) +#define BBP_CSR_CFG_READ_CONTROL FIELD32(0x00010000) +#define BBP_CSR_CFG_BUSY FIELD32(0x00020000) +#define BBP_CSR_CFG_BBP_PAR_DUR FIELD32(0x00040000) +#define BBP_CSR_CFG_BBP_RW_MODE FIELD32(0x00080000) + +/* + * RF_CSR_CFG0: RF control register + * REGID_AND_VALUE: Register value to program into RF + * BITWIDTH: Selected RF register + * STANDBYMODE: 0 high when standby, 1 low when standby + * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate + * BUSY: ASIC is busy executing RF commands + */ +#define RF_CSR_CFG0 0x1020 +#define RF_CSR_CFG0_REGID_AND_VALUE FIELD32(0x00ffffff) +#define RF_CSR_CFG0_BITWIDTH FIELD32(0x1f000000) +#define RF_CSR_CFG0_REG_VALUE_BW FIELD32(0x1fffffff) +#define RF_CSR_CFG0_STANDBYMODE FIELD32(0x20000000) +#define RF_CSR_CFG0_SEL FIELD32(0x40000000) +#define RF_CSR_CFG0_BUSY FIELD32(0x80000000) + +/* + * RF_CSR_CFG1: RF control register + * REGID_AND_VALUE: Register value to program into RF + * RFGAP: Gap between BB_CONTROL_RF and RF_LE + * 0: 3 system clock cycle (37.5usec) + * 1: 5 system clock cycle (62.5usec) + */ +#define RF_CSR_CFG1 0x1024 +#define RF_CSR_CFG1_REGID_AND_VALUE FIELD32(0x00ffffff) +#define RF_CSR_CFG1_RFGAP FIELD32(0x1f000000) + +/* + * RF_CSR_CFG2: RF control register + * VALUE: Register value to program into RF + * RFGAP: Gap between BB_CONTROL_RF and RF_LE + * 0: 3 system clock cycle (37.5usec) + * 1: 5 system clock cycle (62.5usec) + */ +#define RF_CSR_CFG2 0x1028 +#define RF_CSR_CFG2_VALUE FIELD32(0x00ffffff) + +/* + * LED_CFG: LED control + * color LED's: + * 0: off + * 1: blinking upon TX2 + * 2: periodic slow blinking + * 3: always on + * LED polarity: + * 0: active low + * 1: active high + */ +#define LED_CFG 0x102c +#define LED_CFG_ON_PERIOD FIELD32(0x000000ff) +#define LED_CFG_OFF_PERIOD FIELD32(0x0000ff00) +#define LED_CFG_SLOW_BLINK_PERIOD FIELD32(0x003f0000) +#define LED_CFG_R_LED_MODE FIELD32(0x03000000) +#define LED_CFG_G_LED_MODE FIELD32(0x0c000000) +#define LED_CFG_Y_LED_MODE FIELD32(0x30000000) +#define LED_CFG_LED_POLAR FIELD32(0x40000000) + +/* + * XIFS_TIME_CFG: MAC timing + * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX + * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX + * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX + * when MAC doesn't reference BBP signal BBRXEND + * EIFS: unit 1us + * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer + * + */ +#define XIFS_TIME_CFG 0x1100 +#define XIFS_TIME_CFG_CCKM_SIFS_TIME FIELD32(0x000000ff) +#define XIFS_TIME_CFG_OFDM_SIFS_TIME FIELD32(0x0000ff00) +#define XIFS_TIME_CFG_OFDM_XIFS_TIME FIELD32(0x000f0000) +#define XIFS_TIME_CFG_EIFS FIELD32(0x1ff00000) +#define XIFS_TIME_CFG_BB_RXEND_ENABLE FIELD32(0x20000000) + +/* + * BKOFF_SLOT_CFG: + */ +#define BKOFF_SLOT_CFG 0x1104 +#define BKOFF_SLOT_CFG_SLOT_TIME FIELD32(0x000000ff) +#define BKOFF_SLOT_CFG_CC_DELAY_TIME FIELD32(0x0000ff00) + +/* + * NAV_TIME_CFG: + */ +#define NAV_TIME_CFG 0x1108 +#define NAV_TIME_CFG_SIFS FIELD32(0x000000ff) +#define NAV_TIME_CFG_SLOT_TIME FIELD32(0x0000ff00) +#define NAV_TIME_CFG_EIFS FIELD32(0x01ff0000) +#define NAV_TIME_ZERO_SIFS FIELD32(0x02000000) + +/* + * CH_TIME_CFG: count as channel busy + */ +#define CH_TIME_CFG 0x110c + +/* + * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us + */ +#define PBF_LIFE_TIMER 0x1110 + +/* + * BCN_TIME_CFG: + * BEACON_INTERVAL: in unit of 1/16 TU + * TSF_TICKING: Enable TSF auto counting + * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode + * BEACON_GEN: Enable beacon generator + */ +#define BCN_TIME_CFG 0x1114 +#define BCN_TIME_CFG_BEACON_INTERVAL FIELD32(0x0000ffff) +#define BCN_TIME_CFG_TSF_TICKING FIELD32(0x00010000) +#define BCN_TIME_CFG_TSF_SYNC FIELD32(0x00060000) +#define BCN_TIME_CFG_TBTT_ENABLE FIELD32(0x00080000) +#define BCN_TIME_CFG_BEACON_GEN FIELD32(0x00100000) +#define BCN_TIME_CFG_TX_TIME_COMPENSATE FIELD32(0xf0000000) + +/* + * TBTT_SYNC_CFG: + */ +#define TBTT_SYNC_CFG 0x1118 + +/* + * TSF_TIMER_DW0: Local lsb TSF timer, read-only + */ +#define TSF_TIMER_DW0 0x111c +#define TSF_TIMER_DW0_LOW_WORD FIELD32(0xffffffff) + +/* + * TSF_TIMER_DW1: Local msb TSF timer, read-only + */ +#define TSF_TIMER_DW1 0x1120 +#define TSF_TIMER_DW1_HIGH_WORD FIELD32(0xffffffff) + +/* + * TBTT_TIMER: TImer remains till next TBTT, read-only + */ +#define TBTT_TIMER 0x1124 + +/* + * INT_TIMER_CFG: + */ +#define INT_TIMER_CFG 0x1128 + +/* + * INT_TIMER_EN: GP-timer and pre-tbtt Int enable + */ +#define INT_TIMER_EN 0x112c + +/* + * CH_IDLE_STA: channel idle time + */ +#define CH_IDLE_STA 0x1130 + +/* + * CH_BUSY_STA: channel busy time + */ +#define CH_BUSY_STA 0x1134 + +/* + * MAC_STATUS_CFG: + * BBP_RF_BUSY: When set to 0, BBP and RF are stable. + * if 1 or higher one of the 2 registers is busy. + */ +#define MAC_STATUS_CFG 0x1200 +#define MAC_STATUS_CFG_BBP_RF_BUSY FIELD32(0x00000003) + +/* + * PWR_PIN_CFG: + */ +#define PWR_PIN_CFG 0x1204 + +/* + * AUTOWAKEUP_CFG: Manual power control / status register + * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set + * AUTOWAKE: 0:sleep, 1:awake + */ +#define AUTOWAKEUP_CFG 0x1208 +#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME FIELD32(0x000000ff) +#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE FIELD32(0x00007f00) +#define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000) + +/* + * EDCA_AC0_CFG: + */ +#define EDCA_AC0_CFG 0x1300 +#define EDCA_AC0_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC0_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC0_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC0_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_AC1_CFG: + */ +#define EDCA_AC1_CFG 0x1304 +#define EDCA_AC1_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC1_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC1_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC1_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_AC2_CFG: + */ +#define EDCA_AC2_CFG 0x1308 +#define EDCA_AC2_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC2_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC2_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC2_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_AC3_CFG: + */ +#define EDCA_AC3_CFG 0x130c +#define EDCA_AC3_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC3_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC3_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC3_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_TID_AC_MAP: + */ +#define EDCA_TID_AC_MAP 0x1310 + +/* + * TX_PWR_CFG_0: + */ +#define TX_PWR_CFG_0 0x1314 +#define TX_PWR_CFG_0_1MBS FIELD32(0x0000000f) +#define TX_PWR_CFG_0_2MBS FIELD32(0x000000f0) +#define TX_PWR_CFG_0_55MBS FIELD32(0x00000f00) +#define TX_PWR_CFG_0_11MBS FIELD32(0x0000f000) +#define TX_PWR_CFG_0_6MBS FIELD32(0x000f0000) +#define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000) +#define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000) +#define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_1: + */ +#define TX_PWR_CFG_1 0x1318 +#define TX_PWR_CFG_1_24MBS FIELD32(0x0000000f) +#define TX_PWR_CFG_1_36MBS FIELD32(0x000000f0) +#define TX_PWR_CFG_1_48MBS FIELD32(0x00000f00) +#define TX_PWR_CFG_1_54MBS FIELD32(0x0000f000) +#define TX_PWR_CFG_1_MCS0 FIELD32(0x000f0000) +#define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000) +#define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000) +#define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_2: + */ +#define TX_PWR_CFG_2 0x131c +#define TX_PWR_CFG_2_MCS4 FIELD32(0x0000000f) +#define TX_PWR_CFG_2_MCS5 FIELD32(0x000000f0) +#define TX_PWR_CFG_2_MCS6 FIELD32(0x00000f00) +#define TX_PWR_CFG_2_MCS7 FIELD32(0x0000f000) +#define TX_PWR_CFG_2_MCS8 FIELD32(0x000f0000) +#define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000) +#define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000) +#define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_3: + */ +#define TX_PWR_CFG_3 0x1320 +#define TX_PWR_CFG_3_MCS12 FIELD32(0x0000000f) +#define TX_PWR_CFG_3_MCS13 FIELD32(0x000000f0) +#define TX_PWR_CFG_3_MCS14 FIELD32(0x00000f00) +#define TX_PWR_CFG_3_MCS15 FIELD32(0x0000f000) +#define TX_PWR_CFG_3_UKNOWN1 FIELD32(0x000f0000) +#define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000) +#define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000) +#define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_4: + */ +#define TX_PWR_CFG_4 0x1324 +#define TX_PWR_CFG_4_UKNOWN5 FIELD32(0x0000000f) +#define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0) +#define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00) +#define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000) + +/* + * TX_PIN_CFG: + */ +#define TX_PIN_CFG 0x1328 +#define TX_PIN_CFG_PA_PE_A0_EN FIELD32(0x00000001) +#define TX_PIN_CFG_PA_PE_G0_EN FIELD32(0x00000002) +#define TX_PIN_CFG_PA_PE_A1_EN FIELD32(0x00000004) +#define TX_PIN_CFG_PA_PE_G1_EN FIELD32(0x00000008) +#define TX_PIN_CFG_PA_PE_A0_POL FIELD32(0x00000010) +#define TX_PIN_CFG_PA_PE_G0_POL FIELD32(0x00000020) +#define TX_PIN_CFG_PA_PE_A1_POL FIELD32(0x00000040) +#define TX_PIN_CFG_PA_PE_G1_POL FIELD32(0x00000080) +#define TX_PIN_CFG_LNA_PE_A0_EN FIELD32(0x00000100) +#define TX_PIN_CFG_LNA_PE_G0_EN FIELD32(0x00000200) +#define TX_PIN_CFG_LNA_PE_A1_EN FIELD32(0x00000400) +#define TX_PIN_CFG_LNA_PE_G1_EN FIELD32(0x00000800) +#define TX_PIN_CFG_LNA_PE_A0_POL FIELD32(0x00001000) +#define TX_PIN_CFG_LNA_PE_G0_POL FIELD32(0x00002000) +#define TX_PIN_CFG_LNA_PE_A1_POL FIELD32(0x00004000) +#define TX_PIN_CFG_LNA_PE_G1_POL FIELD32(0x00008000) +#define TX_PIN_CFG_RFTR_EN FIELD32(0x00010000) +#define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000) +#define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000) +#define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000) + +/* + * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz + */ +#define TX_BAND_CFG 0x132c +#define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001) +#define TX_BAND_CFG_A FIELD32(0x00000002) +#define TX_BAND_CFG_BG FIELD32(0x00000004) + +/* + * TX_SW_CFG0: + */ +#define TX_SW_CFG0 0x1330 + +/* + * TX_SW_CFG1: + */ +#define TX_SW_CFG1 0x1334 + +/* + * TX_SW_CFG2: + */ +#define TX_SW_CFG2 0x1338 + +/* + * TXOP_THRES_CFG: + */ +#define TXOP_THRES_CFG 0x133c + +/* + * TXOP_CTRL_CFG: + */ +#define TXOP_CTRL_CFG 0x1340 + +/* + * TX_RTS_CFG: + * RTS_THRES: unit:byte + * RTS_FBK_EN: enable rts rate fallback + */ +#define TX_RTS_CFG 0x1344 +#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT FIELD32(0x000000ff) +#define TX_RTS_CFG_RTS_THRES FIELD32(0x00ffff00) +#define TX_RTS_CFG_RTS_FBK_EN FIELD32(0x01000000) + +/* + * TX_TIMEOUT_CFG: + * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us + * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure + * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation. + * it is recommended that: + * (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) + */ +#define TX_TIMEOUT_CFG 0x1348 +#define TX_TIMEOUT_CFG_MPDU_LIFETIME FIELD32(0x000000f0) +#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT FIELD32(0x0000ff00) +#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT FIELD32(0x00ff0000) + +/* + * TX_RTY_CFG: + * SHORT_RTY_LIMIT: short retry limit + * LONG_RTY_LIMIT: long retry limit + * LONG_RTY_THRE: Long retry threshoold + * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode + * 0:expired by retry limit, 1: expired by mpdu life timer + * AGG_RTY_MODE: Aggregate MPDU retry mode + * 0:expired by retry limit, 1: expired by mpdu life timer + * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable + */ +#define TX_RTY_CFG 0x134c +#define TX_RTY_CFG_SHORT_RTY_LIMIT FIELD32(0x000000ff) +#define TX_RTY_CFG_LONG_RTY_LIMIT FIELD32(0x0000ff00) +#define TX_RTY_CFG_LONG_RTY_THRE FIELD32(0x0fff0000) +#define TX_RTY_CFG_NON_AGG_RTY_MODE FIELD32(0x10000000) +#define TX_RTY_CFG_AGG_RTY_MODE FIELD32(0x20000000) +#define TX_RTY_CFG_TX_AUTO_FB_ENABLE FIELD32(0x40000000) + +/* + * TX_LINK_CFG: + * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us + * MFB_ENABLE: TX apply remote MFB 1:enable + * REMOTE_UMFS_ENABLE: remote unsolicit MFB enable + * 0: not apply remote remote unsolicit (MFS=7) + * TX_MRQ_EN: MCS request TX enable + * TX_RDG_EN: RDG TX enable + * TX_CF_ACK_EN: Piggyback CF-ACK enable + * REMOTE_MFB: remote MCS feedback + * REMOTE_MFS: remote MCS feedback sequence number + */ +#define TX_LINK_CFG 0x1350 +#define TX_LINK_CFG_REMOTE_MFB_LIFETIME FIELD32(0x000000ff) +#define TX_LINK_CFG_MFB_ENABLE FIELD32(0x00000100) +#define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200) +#define TX_LINK_CFG_TX_MRQ_EN FIELD32(0x00000400) +#define TX_LINK_CFG_TX_RDG_EN FIELD32(0x00000800) +#define TX_LINK_CFG_TX_CF_ACK_EN FIELD32(0x00001000) +#define TX_LINK_CFG_REMOTE_MFB FIELD32(0x00ff0000) +#define TX_LINK_CFG_REMOTE_MFS FIELD32(0xff000000) + +/* + * HT_FBK_CFG0: + */ +#define HT_FBK_CFG0 0x1354 +#define HT_FBK_CFG0_HTMCS0FBK FIELD32(0x0000000f) +#define HT_FBK_CFG0_HTMCS1FBK FIELD32(0x000000f0) +#define HT_FBK_CFG0_HTMCS2FBK FIELD32(0x00000f00) +#define HT_FBK_CFG0_HTMCS3FBK FIELD32(0x0000f000) +#define HT_FBK_CFG0_HTMCS4FBK FIELD32(0x000f0000) +#define HT_FBK_CFG0_HTMCS5FBK FIELD32(0x00f00000) +#define HT_FBK_CFG0_HTMCS6FBK FIELD32(0x0f000000) +#define HT_FBK_CFG0_HTMCS7FBK FIELD32(0xf0000000) + +/* + * HT_FBK_CFG1: + */ +#define HT_FBK_CFG1 0x1358 +#define HT_FBK_CFG1_HTMCS8FBK FIELD32(0x0000000f) +#define HT_FBK_CFG1_HTMCS9FBK FIELD32(0x000000f0) +#define HT_FBK_CFG1_HTMCS10FBK FIELD32(0x00000f00) +#define HT_FBK_CFG1_HTMCS11FBK FIELD32(0x0000f000) +#define HT_FBK_CFG1_HTMCS12FBK FIELD32(0x000f0000) +#define HT_FBK_CFG1_HTMCS13FBK FIELD32(0x00f00000) +#define HT_FBK_CFG1_HTMCS14FBK FIELD32(0x0f000000) +#define HT_FBK_CFG1_HTMCS15FBK FIELD32(0xf0000000) + +/* + * LG_FBK_CFG0: + */ +#define LG_FBK_CFG0 0x135c +#define LG_FBK_CFG0_OFDMMCS0FBK FIELD32(0x0000000f) +#define LG_FBK_CFG0_OFDMMCS1FBK FIELD32(0x000000f0) +#define LG_FBK_CFG0_OFDMMCS2FBK FIELD32(0x00000f00) +#define LG_FBK_CFG0_OFDMMCS3FBK FIELD32(0x0000f000) +#define LG_FBK_CFG0_OFDMMCS4FBK FIELD32(0x000f0000) +#define LG_FBK_CFG0_OFDMMCS5FBK FIELD32(0x00f00000) +#define LG_FBK_CFG0_OFDMMCS6FBK FIELD32(0x0f000000) +#define LG_FBK_CFG0_OFDMMCS7FBK FIELD32(0xf0000000) + +/* + * LG_FBK_CFG1: + */ +#define LG_FBK_CFG1 0x1360 +#define LG_FBK_CFG0_CCKMCS0FBK FIELD32(0x0000000f) +#define LG_FBK_CFG0_CCKMCS1FBK FIELD32(0x000000f0) +#define LG_FBK_CFG0_CCKMCS2FBK FIELD32(0x00000f00) +#define LG_FBK_CFG0_CCKMCS3FBK FIELD32(0x0000f000) + +/* + * CCK_PROT_CFG: CCK Protection + * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd) + * PROTECT_CTRL: Protection control frame type for CCK TX + * 0:none, 1:RTS/CTS, 2:CTS-to-self + * PROTECT_NAV: TXOP protection type for CCK TX + * 0:none, 1:ShortNAVprotect, 2:LongNAVProtect + * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow + * RTS_TH_EN: RTS threshold enable on CCK TX + */ +#define CCK_PROT_CFG 0x1364 +#define CCK_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define CCK_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define CCK_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define CCK_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define CCK_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define CCK_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define CCK_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define CCK_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define CCK_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define CCK_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * OFDM_PROT_CFG: OFDM Protection + */ +#define OFDM_PROT_CFG 0x1368 +#define OFDM_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define OFDM_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define OFDM_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define OFDM_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * MM20_PROT_CFG: MM20 Protection + */ +#define MM20_PROT_CFG 0x136c +#define MM20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define MM20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define MM20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define MM20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define MM20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define MM20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define MM20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * MM40_PROT_CFG: MM40 Protection + */ +#define MM40_PROT_CFG 0x1370 +#define MM40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define MM40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define MM40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define MM40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define MM40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define MM40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define MM40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * GF20_PROT_CFG: GF20 Protection + */ +#define GF20_PROT_CFG 0x1374 +#define GF20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define GF20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define GF20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define GF20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define GF20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define GF20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define GF20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * GF40_PROT_CFG: GF40 Protection + */ +#define GF40_PROT_CFG 0x1378 +#define GF40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define GF40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define GF40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define GF40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define GF40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define GF40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define GF40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * EXP_CTS_TIME: + */ +#define EXP_CTS_TIME 0x137c + +/* + * EXP_ACK_TIME: + */ +#define EXP_ACK_TIME 0x1380 + +/* + * RX_FILTER_CFG: RX configuration register. + */ +#define RX_FILTER_CFG 0x1400 +#define RX_FILTER_CFG_DROP_CRC_ERROR FIELD32(0x00000001) +#define RX_FILTER_CFG_DROP_PHY_ERROR FIELD32(0x00000002) +#define RX_FILTER_CFG_DROP_NOT_TO_ME FIELD32(0x00000004) +#define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008) +#define RX_FILTER_CFG_DROP_VER_ERROR FIELD32(0x00000010) +#define RX_FILTER_CFG_DROP_MULTICAST FIELD32(0x00000020) +#define RX_FILTER_CFG_DROP_BROADCAST FIELD32(0x00000040) +#define RX_FILTER_CFG_DROP_DUPLICATE FIELD32(0x00000080) +#define RX_FILTER_CFG_DROP_CF_END_ACK FIELD32(0x00000100) +#define RX_FILTER_CFG_DROP_CF_END FIELD32(0x00000200) +#define RX_FILTER_CFG_DROP_ACK FIELD32(0x00000400) +#define RX_FILTER_CFG_DROP_CTS FIELD32(0x00000800) +#define RX_FILTER_CFG_DROP_RTS FIELD32(0x00001000) +#define RX_FILTER_CFG_DROP_PSPOLL FIELD32(0x00002000) +#define RX_FILTER_CFG_DROP_BA FIELD32(0x00004000) +#define RX_FILTER_CFG_DROP_BAR FIELD32(0x00008000) +#define RX_FILTER_CFG_DROP_CNTL FIELD32(0x00010000) + +/* + * AUTO_RSP_CFG: + * AUTORESPONDER: 0: disable, 1: enable + * BAC_ACK_POLICY: 0:long, 1:short preamble + * CTS_40_MMODE: Response CTS 40MHz duplicate mode + * CTS_40_MREF: Response CTS 40MHz duplicate mode + * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble + * DUAL_CTS_EN: Power bit value in control frame + * ACK_CTS_PSM_BIT:Power bit value in control frame + */ +#define AUTO_RSP_CFG 0x1404 +#define AUTO_RSP_CFG_AUTORESPONDER FIELD32(0x00000001) +#define AUTO_RSP_CFG_BAC_ACK_POLICY FIELD32(0x00000002) +#define AUTO_RSP_CFG_CTS_40_MMODE FIELD32(0x00000004) +#define AUTO_RSP_CFG_CTS_40_MREF FIELD32(0x00000008) +#define AUTO_RSP_CFG_AR_PREAMBLE FIELD32(0x00000010) +#define AUTO_RSP_CFG_DUAL_CTS_EN FIELD32(0x00000040) +#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT FIELD32(0x00000080) + +/* + * LEGACY_BASIC_RATE: + */ +#define LEGACY_BASIC_RATE 0x1408 + +/* + * HT_BASIC_RATE: + */ +#define HT_BASIC_RATE 0x140c + +/* + * HT_CTRL_CFG: + */ +#define HT_CTRL_CFG 0x1410 + +/* + * SIFS_COST_CFG: + */ +#define SIFS_COST_CFG 0x1414 + +/* + * RX_PARSER_CFG: + * Set NAV for all received frames + */ +#define RX_PARSER_CFG 0x1418 + +/* + * TX_SEC_CNT0: + */ +#define TX_SEC_CNT0 0x1500 + +/* + * RX_SEC_CNT0: + */ +#define RX_SEC_CNT0 0x1504 + +/* + * CCMP_FC_MUTE: + */ +#define CCMP_FC_MUTE 0x1508 + +/* + * TXOP_HLDR_ADDR0: + */ +#define TXOP_HLDR_ADDR0 0x1600 + +/* + * TXOP_HLDR_ADDR1: + */ +#define TXOP_HLDR_ADDR1 0x1604 + +/* + * TXOP_HLDR_ET: + */ +#define TXOP_HLDR_ET 0x1608 + +/* + * QOS_CFPOLL_RA_DW0: + */ +#define QOS_CFPOLL_RA_DW0 0x160c + +/* + * QOS_CFPOLL_RA_DW1: + */ +#define QOS_CFPOLL_RA_DW1 0x1610 + +/* + * QOS_CFPOLL_QC: + */ +#define QOS_CFPOLL_QC 0x1614 + +/* + * RX_STA_CNT0: RX PLCP error count & RX CRC error count + */ +#define RX_STA_CNT0 0x1700 +#define RX_STA_CNT0_CRC_ERR FIELD32(0x0000ffff) +#define RX_STA_CNT0_PHY_ERR FIELD32(0xffff0000) + +/* + * RX_STA_CNT1: RX False CCA count & RX LONG frame count + */ +#define RX_STA_CNT1 0x1704 +#define RX_STA_CNT1_FALSE_CCA FIELD32(0x0000ffff) +#define RX_STA_CNT1_PLCP_ERR FIELD32(0xffff0000) + +/* + * RX_STA_CNT2: */ -#define E2PROM_CSR 0x0004 -#define E2PROM_CSR_DATA_CLOCK FIELD32(0x00000001) -#define E2PROM_CSR_CHIP_SELECT FIELD32(0x00000002) -#define E2PROM_CSR_DATA_IN FIELD32(0x00000004) -#define E2PROM_CSR_DATA_OUT FIELD32(0x00000008) -#define E2PROM_CSR_TYPE FIELD32(0x00000030) -#define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040) -#define E2PROM_CSR_RELOAD FIELD32(0x00000080) +#define RX_STA_CNT2 0x1708 +#define RX_STA_CNT2_RX_DUPLI_COUNT FIELD32(0x0000ffff) +#define RX_STA_CNT2_RX_FIFO_OVERFLOW FIELD32(0xffff0000) /* - * Queue register offset macros + * TX_STA_CNT0: TX Beacon count */ -#define TX_QUEUE_REG_OFFSET 0x10 -#define TX_BASE_PTR(__x) TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET) -#define TX_MAX_CNT(__x) TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET) -#define TX_CTX_IDX(__x) TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET) -#define TX_DTX_IDX(__x) TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET) +#define TX_STA_CNT0 0x170c +#define TX_STA_CNT0_TX_FAIL_COUNT FIELD32(0x0000ffff) +#define TX_STA_CNT0_TX_BEACON_COUNT FIELD32(0xffff0000) /* - * EFUSE_CSR: RT3090 EEPROM + * TX_STA_CNT1: TX tx count */ -#define EFUSE_CTRL 0x0580 -#define EFUSE_CTRL_ADDRESS_IN FIELD32(0x03fe0000) -#define EFUSE_CTRL_MODE FIELD32(0x000000c0) -#define EFUSE_CTRL_KICK FIELD32(0x40000000) +#define TX_STA_CNT1 0x1710 +#define TX_STA_CNT1_TX_SUCCESS FIELD32(0x0000ffff) +#define TX_STA_CNT1_TX_RETRANSMIT FIELD32(0xffff0000) /* - * EFUSE_DATA0 + * TX_STA_CNT2: TX tx count */ -#define EFUSE_DATA0 0x0590 +#define TX_STA_CNT2 0x1714 +#define TX_STA_CNT2_TX_ZERO_LEN_COUNT FIELD32(0x0000ffff) +#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) /* - * EFUSE_DATA1 + * TX_STA_FIFO: TX Result for specific PID status fifo register */ -#define EFUSE_DATA1 0x0594 +#define TX_STA_FIFO 0x1718 +#define TX_STA_FIFO_VALID FIELD32(0x00000001) +#define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e) +#define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020) +#define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040) +#define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080) +#define TX_STA_FIFO_WCID FIELD32(0x0000ff00) +#define TX_STA_FIFO_MCS FIELD32(0x007f0000) +#define TX_STA_FIFO_PHYMODE FIELD32(0xc0000000) /* - * EFUSE_DATA2 + * TX_AGG_CNT: Debug counter */ -#define EFUSE_DATA2 0x0598 +#define TX_AGG_CNT 0x171c +#define TX_AGG_CNT_NON_AGG_TX_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT_AGG_TX_COUNT FIELD32(0xffff0000) /* - * EFUSE_DATA3 + * TX_AGG_CNT0: */ -#define EFUSE_DATA3 0x059c +#define TX_AGG_CNT0 0x1720 +#define TX_AGG_CNT0_AGG_SIZE_1_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT0_AGG_SIZE_2_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT1: + */ +#define TX_AGG_CNT1 0x1724 +#define TX_AGG_CNT1_AGG_SIZE_3_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT1_AGG_SIZE_4_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT2: + */ +#define TX_AGG_CNT2 0x1728 +#define TX_AGG_CNT2_AGG_SIZE_5_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT2_AGG_SIZE_6_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT3: + */ +#define TX_AGG_CNT3 0x172c +#define TX_AGG_CNT3_AGG_SIZE_7_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT3_AGG_SIZE_8_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT4: + */ +#define TX_AGG_CNT4 0x1730 +#define TX_AGG_CNT4_AGG_SIZE_9_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT4_AGG_SIZE_10_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT5: + */ +#define TX_AGG_CNT5 0x1734 +#define TX_AGG_CNT5_AGG_SIZE_11_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT5_AGG_SIZE_12_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT6: + */ +#define TX_AGG_CNT6 0x1738 +#define TX_AGG_CNT6_AGG_SIZE_13_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT6_AGG_SIZE_14_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT7: + */ +#define TX_AGG_CNT7 0x173c +#define TX_AGG_CNT7_AGG_SIZE_15_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT7_AGG_SIZE_16_COUNT FIELD32(0xffff0000) + +/* + * MPDU_DENSITY_CNT: + * TX_ZERO_DEL: TX zero length delimiter count + * RX_ZERO_DEL: RX zero length delimiter count + */ +#define MPDU_DENSITY_CNT 0x1740 +#define MPDU_DENSITY_CNT_TX_ZERO_DEL FIELD32(0x0000ffff) +#define MPDU_DENSITY_CNT_RX_ZERO_DEL FIELD32(0xffff0000) + +/* + * Security key table memory. + * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry + * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry + * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry + * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry + * SHARED_KEY_TABLE_BASE: 32 bytes * 32-entry + * SHARED_KEY_MODE_BASE: 4 bits * 32-entry + */ +#define MAC_WCID_BASE 0x1800 +#define PAIRWISE_KEY_TABLE_BASE 0x4000 +#define MAC_IVEIV_TABLE_BASE 0x6000 +#define MAC_WCID_ATTRIBUTE_BASE 0x6800 +#define SHARED_KEY_TABLE_BASE 0x6c00 +#define SHARED_KEY_MODE_BASE 0x7000 + +#define MAC_WCID_ENTRY(__idx) \ + ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) ) +#define PAIRWISE_KEY_ENTRY(__idx) \ + ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) +#define MAC_IVEIV_ENTRY(__idx) \ + ( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) ) +#define MAC_WCID_ATTR_ENTRY(__idx) \ + ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) +#define SHARED_KEY_ENTRY(__idx) \ + ( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) +#define SHARED_KEY_MODE_ENTRY(__idx) \ + ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) ) + +struct mac_wcid_entry { + u8 mac[6]; + u8 reserved[2]; +} __attribute__ ((packed)); + +struct hw_key_entry { + u8 key[16]; + u8 tx_mic[8]; + u8 rx_mic[8]; +} __attribute__ ((packed)); + +struct mac_iveiv_entry { + u8 iv[8]; +} __attribute__ ((packed)); + +/* + * MAC_WCID_ATTRIBUTE: + */ +#define MAC_WCID_ATTRIBUTE_KEYTAB FIELD32(0x00000001) +#define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e) +#define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) +#define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) + +/* + * SHARED_KEY_MODE: + */ +#define SHARED_KEY_MODE_BSS0_KEY0 FIELD32(0x00000007) +#define SHARED_KEY_MODE_BSS0_KEY1 FIELD32(0x00000070) +#define SHARED_KEY_MODE_BSS0_KEY2 FIELD32(0x00000700) +#define SHARED_KEY_MODE_BSS0_KEY3 FIELD32(0x00007000) +#define SHARED_KEY_MODE_BSS1_KEY0 FIELD32(0x00070000) +#define SHARED_KEY_MODE_BSS1_KEY1 FIELD32(0x00700000) +#define SHARED_KEY_MODE_BSS1_KEY2 FIELD32(0x07000000) +#define SHARED_KEY_MODE_BSS1_KEY3 FIELD32(0x70000000) + +/* + * HOST-MCU communication + */ + +/* + * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. + */ +#define H2M_MAILBOX_CSR 0x7010 +#define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff) +#define H2M_MAILBOX_CSR_ARG1 FIELD32(0x0000ff00) +#define H2M_MAILBOX_CSR_CMD_TOKEN FIELD32(0x00ff0000) +#define H2M_MAILBOX_CSR_OWNER FIELD32(0xff000000) + +/* + * H2M_MAILBOX_CID: + */ +#define H2M_MAILBOX_CID 0x7014 +#define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff) +#define H2M_MAILBOX_CID_CMD1 FIELD32(0x0000ff00) +#define H2M_MAILBOX_CID_CMD2 FIELD32(0x00ff0000) +#define H2M_MAILBOX_CID_CMD3 FIELD32(0xff000000) + +/* + * H2M_MAILBOX_STATUS: + */ +#define H2M_MAILBOX_STATUS 0x701c + +/* + * H2M_INT_SRC: + */ +#define H2M_INT_SRC 0x7024 + +/* + * H2M_BBP_AGENT: + */ +#define H2M_BBP_AGENT 0x7028 + +/* + * MCU_LEDCS: LED control for MCU Mailbox. + */ +#define MCU_LEDCS_LED_MODE FIELD8(0x1f) +#define MCU_LEDCS_POLARITY FIELD8(0x01) + +/* + * HW_CS_CTS_BASE: + * Carrier-sense CTS frame base address. + * It's where mac stores carrier-sense frame for carrier-sense function. + */ +#define HW_CS_CTS_BASE 0x7700 + +/* + * HW_DFS_CTS_BASE: + * FS CTS frame base address. It's where mac stores CTS frame for DFS. + */ +#define HW_DFS_CTS_BASE 0x7780 + +/* + * TXRX control registers - base address 0x3000 + */ + +/* + * TXRX_CSR1: + * rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. + */ +#define TXRX_CSR1 0x77d0 + +/* + * HW_DEBUG_SETTING_BASE: + * since NULL frame won't be that long (256 byte) + * We steal 16 tail bytes to save debugging settings + */ +#define HW_DEBUG_SETTING_BASE 0x77f0 +#define HW_DEBUG_SETTING_BASE2 0x7770 + +/* + * HW_BEACON_BASE + * In order to support maximum 8 MBSS and its maximum length + * is 512 bytes for each beacon + * Three section discontinue memory segments will be used. + * 1. The original region for BCN 0~3 + * 2. Extract memory from FCE table for BCN 4~5 + * 3. Extract memory from Pair-wise key table for BCN 6~7 + * It occupied those memory of wcid 238~253 for BCN 6 + * and wcid 222~237 for BCN 7 + * + * IMPORTANT NOTE: Not sure why legacy driver does this, + * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6. + */ +#define HW_BEACON_BASE0 0x7800 +#define HW_BEACON_BASE1 0x7a00 +#define HW_BEACON_BASE2 0x7c00 +#define HW_BEACON_BASE3 0x7e00 +#define HW_BEACON_BASE4 0x7200 +#define HW_BEACON_BASE5 0x7400 +#define HW_BEACON_BASE6 0x5dc0 +#define HW_BEACON_BASE7 0x5bc0 + +#define HW_BEACON_OFFSET(__index) \ + ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \ + (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \ + (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) ) /* * 8051 firmware image. @@ -89,11 +1492,282 @@ #define FIRMWARE_RT2860 "rt2860.bin" #define FIRMWARE_IMAGE_BASE 0x2000 +/* + * BBP registers. + * The wordsize of the BBP is 8 bits. + */ + +/* + * BBP 1: TX Antenna + */ +#define BBP1_TX_POWER FIELD8(0x07) +#define BBP1_TX_ANTENNA FIELD8(0x18) + +/* + * BBP 3: RX Antenna + */ +#define BBP3_RX_ANTENNA FIELD8(0x18) +#define BBP3_HT40_PLUS FIELD8(0x20) + +/* + * BBP 4: Bandwidth + */ +#define BBP4_TX_BF FIELD8(0x01) +#define BBP4_BANDWIDTH FIELD8(0x18) + +/* + * RFCSR registers + * The wordsize of the RFCSR is 8 bits. + */ + +/* + * RFCSR 6: + */ +#define RFCSR6_R FIELD8(0x03) + +/* + * RFCSR 7: + */ +#define RFCSR7_RF_TUNING FIELD8(0x01) + +/* + * RFCSR 12: + */ +#define RFCSR12_TX_POWER FIELD8(0x1f) + +/* + * RFCSR 22: + */ +#define RFCSR22_BASEBAND_LOOPBACK FIELD8(0x01) + +/* + * RFCSR 23: + */ +#define RFCSR23_FREQ_OFFSET FIELD8(0x7f) + +/* + * RFCSR 30: + */ +#define RFCSR30_RF_CALIBRATION FIELD8(0x80) + +/* + * RF registers + */ + +/* + * RF 2 + */ +#define RF2_ANTENNA_RX2 FIELD32(0x00000040) +#define RF2_ANTENNA_TX1 FIELD32(0x00004000) +#define RF2_ANTENNA_RX1 FIELD32(0x00020000) + +/* + * RF 3 + */ +#define RF3_TXPOWER_G FIELD32(0x00003e00) +#define RF3_TXPOWER_A_7DBM_BOOST FIELD32(0x00000200) +#define RF3_TXPOWER_A FIELD32(0x00003c00) + +/* + * RF 4 + */ +#define RF4_TXPOWER_G FIELD32(0x000007c0) +#define RF4_TXPOWER_A_7DBM_BOOST FIELD32(0x00000040) +#define RF4_TXPOWER_A FIELD32(0x00000780) +#define RF4_FREQ_OFFSET FIELD32(0x001f8000) +#define RF4_HT40 FIELD32(0x00200000) + +/* + * EEPROM content. + * The wordsize of the EEPROM is 16 bits. + */ + +/* + * EEPROM Version + */ +#define EEPROM_VERSION 0x0001 +#define EEPROM_VERSION_FAE FIELD16(0x00ff) +#define EEPROM_VERSION_VERSION FIELD16(0xff00) + +/* + * HW MAC address. + */ +#define EEPROM_MAC_ADDR_0 0x0002 +#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) +#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) +#define EEPROM_MAC_ADDR_1 0x0003 +#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) +#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) +#define EEPROM_MAC_ADDR_2 0x0004 +#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) +#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) + +/* + * EEPROM ANTENNA config + * RXPATH: 1: 1R, 2: 2R, 3: 3R + * TXPATH: 1: 1T, 2: 2T + */ +#define EEPROM_ANTENNA 0x001a +#define EEPROM_ANTENNA_RXPATH FIELD16(0x000f) +#define EEPROM_ANTENNA_TXPATH FIELD16(0x00f0) +#define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0f00) + +/* + * EEPROM NIC config + * CARDBUS_ACCEL: 0 - enable, 1 - disable + */ +#define EEPROM_NIC 0x001b +#define EEPROM_NIC_HW_RADIO FIELD16(0x0001) +#define EEPROM_NIC_DYNAMIC_TX_AGC FIELD16(0x0002) +#define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0004) +#define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0008) +#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0010) +#define EEPROM_NIC_BW40M_SB_BG FIELD16(0x0020) +#define EEPROM_NIC_BW40M_SB_A FIELD16(0x0040) +#define EEPROM_NIC_WPS_PBC FIELD16(0x0080) +#define EEPROM_NIC_BW40M_BG FIELD16(0x0100) +#define EEPROM_NIC_BW40M_A FIELD16(0x0200) + +/* + * EEPROM frequency + */ +#define EEPROM_FREQ 0x001d +#define EEPROM_FREQ_OFFSET FIELD16(0x00ff) +#define EEPROM_FREQ_LED_MODE FIELD16(0x7f00) +#define EEPROM_FREQ_LED_POLARITY FIELD16(0x1000) + +/* + * EEPROM LED + * POLARITY_RDY_G: Polarity RDY_G setting. + * POLARITY_RDY_A: Polarity RDY_A setting. + * POLARITY_ACT: Polarity ACT setting. + * POLARITY_GPIO_0: Polarity GPIO0 setting. + * POLARITY_GPIO_1: Polarity GPIO1 setting. + * POLARITY_GPIO_2: Polarity GPIO2 setting. + * POLARITY_GPIO_3: Polarity GPIO3 setting. + * POLARITY_GPIO_4: Polarity GPIO4 setting. + * LED_MODE: Led mode. + */ +#define EEPROM_LED1 0x001e +#define EEPROM_LED2 0x001f +#define EEPROM_LED3 0x0020 +#define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001) +#define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002) +#define EEPROM_LED_POLARITY_ACT FIELD16(0x0004) +#define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008) +#define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010) +#define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020) +#define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040) +#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080) +#define EEPROM_LED_LED_MODE FIELD16(0x1f00) + +/* + * EEPROM LNA + */ +#define EEPROM_LNA 0x0022 +#define EEPROM_LNA_BG FIELD16(0x00ff) +#define EEPROM_LNA_A0 FIELD16(0xff00) + +/* + * EEPROM RSSI BG offset + */ +#define EEPROM_RSSI_BG 0x0023 +#define EEPROM_RSSI_BG_OFFSET0 FIELD16(0x00ff) +#define EEPROM_RSSI_BG_OFFSET1 FIELD16(0xff00) + +/* + * EEPROM RSSI BG2 offset + */ +#define EEPROM_RSSI_BG2 0x0024 +#define EEPROM_RSSI_BG2_OFFSET2 FIELD16(0x00ff) +#define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00) + +/* + * EEPROM RSSI A offset + */ +#define EEPROM_RSSI_A 0x0025 +#define EEPROM_RSSI_A_OFFSET0 FIELD16(0x00ff) +#define EEPROM_RSSI_A_OFFSET1 FIELD16(0xff00) + +/* + * EEPROM RSSI A2 offset + */ +#define EEPROM_RSSI_A2 0x0026 +#define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff) +#define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) + +/* + * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power. + * This is delta in 40MHZ. + * VALUE: Tx Power dalta value (MAX=4) + * TYPE: 1: Plus the delta value, 0: minus the delta value + * TXPOWER: Enable: + */ +#define EEPROM_TXPOWER_DELTA 0x0028 +#define EEPROM_TXPOWER_DELTA_VALUE FIELD16(0x003f) +#define EEPROM_TXPOWER_DELTA_TYPE FIELD16(0x0040) +#define EEPROM_TXPOWER_DELTA_TXPOWER FIELD16(0x0080) + +/* + * EEPROM TXPOWER 802.11BG + */ +#define EEPROM_TXPOWER_BG1 0x0029 +#define EEPROM_TXPOWER_BG2 0x0030 +#define EEPROM_TXPOWER_BG_SIZE 7 +#define EEPROM_TXPOWER_BG_1 FIELD16(0x00ff) +#define EEPROM_TXPOWER_BG_2 FIELD16(0xff00) + +/* + * EEPROM TXPOWER 802.11A + */ +#define EEPROM_TXPOWER_A1 0x003c +#define EEPROM_TXPOWER_A2 0x0053 +#define EEPROM_TXPOWER_A_SIZE 6 +#define EEPROM_TXPOWER_A_1 FIELD16(0x00ff) +#define EEPROM_TXPOWER_A_2 FIELD16(0xff00) + +/* + * EEPROM TXpower byrate: 20MHZ power + */ +#define EEPROM_TXPOWER_BYRATE 0x006f + +/* + * EEPROM BBP. + */ +#define EEPROM_BBP_START 0x0078 +#define EEPROM_BBP_SIZE 16 +#define EEPROM_BBP_VALUE FIELD16(0x00ff) +#define EEPROM_BBP_REG_ID FIELD16(0xff00) + +/* + * MCU mailbox commands. + */ +#define MCU_SLEEP 0x30 +#define MCU_WAKEUP 0x31 +#define MCU_RADIO_OFF 0x35 +#define MCU_CURRENT 0x36 +#define MCU_LED 0x50 +#define MCU_LED_STRENGTH 0x51 +#define MCU_LED_1 0x52 +#define MCU_LED_2 0x53 +#define MCU_LED_3 0x54 +#define MCU_RADAR 0x60 +#define MCU_BOOT_SIGNAL 0x72 +#define MCU_BBP_SIGNAL 0x80 +#define MCU_POWER_SAVE 0x83 + +/* + * MCU mailbox tokens + */ +#define TOKEN_WAKUP 3 + /* * DMA descriptor defines. */ #define TXD_DESC_SIZE ( 4 * sizeof(__le32) ) +#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) ) #define RXD_DESC_SIZE ( 4 * sizeof(__le32) ) +#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) /* * TX descriptor format for TX, PRIO and Beacon Ring. @@ -131,6 +1805,52 @@ #define TXD_W3_UCO FIELD32(0x40000000) #define TXD_W3_ICO FIELD32(0x80000000) +/* + * TX WI structure + */ + +/* + * Word0 + * FRAG: 1 To inform TKIP engine this is a fragment. + * MIMO_PS: The remote peer is in dynamic MIMO-PS mode + * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs + * BW: Channel bandwidth 20MHz or 40 MHz + * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED + */ +#define TXWI_W0_FRAG FIELD32(0x00000001) +#define TXWI_W0_MIMO_PS FIELD32(0x00000002) +#define TXWI_W0_CF_ACK FIELD32(0x00000004) +#define TXWI_W0_TS FIELD32(0x00000008) +#define TXWI_W0_AMPDU FIELD32(0x00000010) +#define TXWI_W0_MPDU_DENSITY FIELD32(0x000000e0) +#define TXWI_W0_TX_OP FIELD32(0x00000300) +#define TXWI_W0_MCS FIELD32(0x007f0000) +#define TXWI_W0_BW FIELD32(0x00800000) +#define TXWI_W0_SHORT_GI FIELD32(0x01000000) +#define TXWI_W0_STBC FIELD32(0x06000000) +#define TXWI_W0_IFS FIELD32(0x08000000) +#define TXWI_W0_PHYMODE FIELD32(0xc0000000) + +/* + * Word1 + */ +#define TXWI_W1_ACK FIELD32(0x00000001) +#define TXWI_W1_NSEQ FIELD32(0x00000002) +#define TXWI_W1_BW_WIN_SIZE FIELD32(0x000000fc) +#define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00) +#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) +#define TXWI_W1_PACKETID FIELD32(0xf0000000) + +/* + * Word2 + */ +#define TXWI_W2_IV FIELD32(0xffffffff) + +/* + * Word3 + */ +#define TXWI_W3_EIV FIELD32(0xffffffff) + /* * RX descriptor format for RX Ring. */ @@ -177,4 +1897,64 @@ #define RXD_W3_PLCP_SIGNAL FIELD32(0x00020000) #define RXD_W3_PLCP_RSSI FIELD32(0x00040000) +/* + * RX WI structure + */ + +/* + * Word0 + */ +#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff) +#define RXWI_W0_KEY_INDEX FIELD32(0x00000300) +#define RXWI_W0_BSSID FIELD32(0x00001c00) +#define RXWI_W0_UDF FIELD32(0x0000e000) +#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) +#define RXWI_W0_TID FIELD32(0xf0000000) + +/* + * Word1 + */ +#define RXWI_W1_FRAG FIELD32(0x0000000f) +#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0) +#define RXWI_W1_MCS FIELD32(0x007f0000) +#define RXWI_W1_BW FIELD32(0x00800000) +#define RXWI_W1_SHORT_GI FIELD32(0x01000000) +#define RXWI_W1_STBC FIELD32(0x06000000) +#define RXWI_W1_PHYMODE FIELD32(0xc0000000) + +/* + * Word2 + */ +#define RXWI_W2_RSSI0 FIELD32(0x000000ff) +#define RXWI_W2_RSSI1 FIELD32(0x0000ff00) +#define RXWI_W2_RSSI2 FIELD32(0x00ff0000) + +/* + * Word3 + */ +#define RXWI_W3_SNR0 FIELD32(0x000000ff) +#define RXWI_W3_SNR1 FIELD32(0x0000ff00) + +/* + * Macros for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. + */ +#define MIN_G_TXPOWER 0 +#define MIN_A_TXPOWER -7 +#define MAX_G_TXPOWER 31 +#define MAX_A_TXPOWER 15 +#define DEFAULT_TXPOWER 5 + +#define TXPOWER_G_FROM_DEV(__txpower) \ + ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) + +#define TXPOWER_G_TO_DEV(__txpower) \ + clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER) + +#define TXPOWER_A_FROM_DEV(__txpower) \ + ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) + +#define TXPOWER_A_TO_DEV(__txpower) \ + clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER) + #endif /* RT2800PCI_H */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c index ce2e893856c1..9fe770f7d7bb 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c @@ -34,8 +34,6 @@ #include "rt2x00.h" #include "rt2x00usb.h" -#include "rt2800lib.h" -#include "rt2800.h" #include "rt2800usb.h" /* @@ -45,6 +43,1027 @@ static int modparam_nohwcrypt = 1; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); +/* + * Register access. + * All access to the CSR registers will go through the methods + * rt2x00usb_register_read and rt2x00usb_register_write. + * BBP and RF register require indirect register access, + * and use the CSR registers BBPCSR and RFCSR to achieve this. + * These indirect registers work with busy bits, + * and we will try maximal REGISTER_BUSY_COUNT times to access + * the register while taking a REGISTER_BUSY_DELAY us delay + * between each attampt. When the busy bit is still set at that time, + * the access attempt is considered to have failed, + * and we will print an error. + * The _lock versions must be used if you already hold the csr_mutex + */ +#define WAIT_FOR_BBP(__dev, __reg) \ + rt2x00usb_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg)) +#define WAIT_FOR_RFCSR(__dev, __reg) \ + rt2x00usb_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg)) +#define WAIT_FOR_RF(__dev, __reg) \ + rt2x00usb_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg)) +#define WAIT_FOR_MCU(__dev, __reg) \ + rt2x00usb_regbusy_read((__dev), H2M_MAILBOX_CSR, \ + H2M_MAILBOX_CSR_OWNER, (__reg)) + +static void rt2800usb_bbp_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u8 value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the BBP becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, BBP_CSR_CFG_VALUE, value); + rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); + rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); + + rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_bbp_read(struct rt2x00_dev *rt2x00dev, + const unsigned int word, u8 *value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the BBP becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. + */ + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); + rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); + + rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); + + WAIT_FOR_BBP(rt2x00dev, ®); + } + + *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE); + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_rfcsr_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u8 value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the RFCSR becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RF_CSR_CFG_DATA, value); + rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 1); + rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); + + rt2x00usb_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_rfcsr_read(struct rt2x00_dev *rt2x00dev, + const unsigned int word, u8 *value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the RFCSR becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. + */ + if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 0); + rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); + + rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); + + WAIT_FOR_RFCSR(rt2x00dev, ®); + } + + *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA); + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_rf_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u32 value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the RF becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_RF(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RF_CSR_CFG0_REG_VALUE_BW, value); + rt2x00_set_field32(®, RF_CSR_CFG0_STANDBYMODE, 0); + rt2x00_set_field32(®, RF_CSR_CFG0_SEL, 0); + rt2x00_set_field32(®, RF_CSR_CFG0_BUSY, 1); + + rt2x00usb_register_write_lock(rt2x00dev, RF_CSR_CFG0, reg); + rt2x00_rf_write(rt2x00dev, word, value); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_mcu_request(struct rt2x00_dev *rt2x00dev, + const u8 command, const u8 token, + const u8 arg0, const u8 arg1) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the MCU becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_MCU(rt2x00dev, ®)) { + rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); + rt2x00usb_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg); + + reg = 0; + rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); + rt2x00usb_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +#ifdef CONFIG_RT2X00_LIB_DEBUGFS +static const struct rt2x00debug rt2800usb_rt2x00debug = { + .owner = THIS_MODULE, + .csr = { + .read = rt2x00usb_register_read, + .write = rt2x00usb_register_write, + .flags = RT2X00DEBUGFS_OFFSET, + .word_base = CSR_REG_BASE, + .word_size = sizeof(u32), + .word_count = CSR_REG_SIZE / sizeof(u32), + }, + .eeprom = { + .read = rt2x00_eeprom_read, + .write = rt2x00_eeprom_write, + .word_base = EEPROM_BASE, + .word_size = sizeof(u16), + .word_count = EEPROM_SIZE / sizeof(u16), + }, + .bbp = { + .read = rt2800usb_bbp_read, + .write = rt2800usb_bbp_write, + .word_base = BBP_BASE, + .word_size = sizeof(u8), + .word_count = BBP_SIZE / sizeof(u8), + }, + .rf = { + .read = rt2x00_rf_read, + .write = rt2800usb_rf_write, + .word_base = RF_BASE, + .word_size = sizeof(u32), + .word_count = RF_SIZE / sizeof(u32), + }, +}; +#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ + +static int rt2800usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); +} + +#ifdef CONFIG_RT2X00_LIB_LEDS +static void rt2800usb_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + unsigned int enabled = brightness != LED_OFF; + unsigned int bg_mode = + (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); + unsigned int polarity = + rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, + EEPROM_FREQ_LED_POLARITY); + unsigned int ledmode = + rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, + EEPROM_FREQ_LED_MODE); + + if (led->type == LED_TYPE_RADIO) { + rt2800usb_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, + enabled ? 0x20 : 0); + } else if (led->type == LED_TYPE_ASSOC) { + rt2800usb_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, + enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); + } else if (led->type == LED_TYPE_QUALITY) { + /* + * The brightness is divided into 6 levels (0 - 5), + * The specs tell us the following levels: + * 0, 1 ,3, 7, 15, 31 + * to determine the level in a simple way we can simply + * work with bitshifting: + * (1 << level) - 1 + */ + rt2800usb_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, + (1 << brightness / (LED_FULL / 6)) - 1, + polarity); + } +} + +static int rt2800usb_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + u32 reg; + + rt2x00usb_register_read(led->rt2x00dev, LED_CFG, ®); + rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); + rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); + rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); + rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); + rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 12); + rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); + rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); + rt2x00usb_register_write(led->rt2x00dev, LED_CFG, reg); + + return 0; +} + +static void rt2800usb_init_led(struct rt2x00_dev *rt2x00dev, + struct rt2x00_led *led, + enum led_type type) +{ + led->rt2x00dev = rt2x00dev; + led->type = type; + led->led_dev.brightness_set = rt2800usb_brightness_set; + led->led_dev.blink_set = rt2800usb_blink_set; + led->flags = LED_INITIALIZED; +} +#endif /* CONFIG_RT2X00_LIB_LEDS */ + +/* + * Configuration handlers. + */ +static void rt2800usb_config_wcid_attr(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) +{ + struct mac_wcid_entry wcid_entry; + struct mac_iveiv_entry iveiv_entry; + u32 offset; + u32 reg; + + offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); + + rt2x00usb_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, + !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, + (crypto->cmd == SET_KEY) * crypto->cipher); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, + (crypto->cmd == SET_KEY) * crypto->bssidx); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); + rt2x00usb_register_write(rt2x00dev, offset, reg); + + offset = MAC_IVEIV_ENTRY(key->hw_key_idx); + + memset(&iveiv_entry, 0, sizeof(iveiv_entry)); + if ((crypto->cipher == CIPHER_TKIP) || + (crypto->cipher == CIPHER_TKIP_NO_MIC) || + (crypto->cipher == CIPHER_AES)) + iveiv_entry.iv[3] |= 0x20; + iveiv_entry.iv[3] |= key->keyidx << 6; + rt2x00usb_register_multiwrite(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); + + offset = MAC_WCID_ENTRY(key->hw_key_idx); + + memset(&wcid_entry, 0, sizeof(wcid_entry)); + if (crypto->cmd == SET_KEY) + memcpy(&wcid_entry, crypto->address, ETH_ALEN); + rt2x00usb_register_multiwrite(rt2x00dev, offset, + &wcid_entry, sizeof(wcid_entry)); +} + +static int rt2800usb_config_shared_key(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) +{ + struct hw_key_entry key_entry; + struct rt2x00_field32 field; + int timeout; + u32 offset; + u32 reg; + + if (crypto->cmd == SET_KEY) { + key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx; + + memcpy(key_entry.key, crypto->key, + sizeof(key_entry.key)); + memcpy(key_entry.tx_mic, crypto->tx_mic, + sizeof(key_entry.tx_mic)); + memcpy(key_entry.rx_mic, crypto->rx_mic, + sizeof(key_entry.rx_mic)); + + offset = SHARED_KEY_ENTRY(key->hw_key_idx); + timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); + rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, + offset, &key_entry, + sizeof(key_entry), + timeout); + } + + /* + * The cipher types are stored over multiple registers + * starting with SHARED_KEY_MODE_BASE each word will have + * 32 bits and contains the cipher types for 2 bssidx each. + * Using the correct defines correctly will cause overhead, + * so just calculate the correct offset. + */ + field.bit_offset = 4 * (key->hw_key_idx % 8); + field.bit_mask = 0x7 << field.bit_offset; + + offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); + + rt2x00usb_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, field, + (crypto->cmd == SET_KEY) * crypto->cipher); + rt2x00usb_register_write(rt2x00dev, offset, reg); + + /* + * Update WCID information + */ + rt2800usb_config_wcid_attr(rt2x00dev, crypto, key); + + return 0; +} + +static int rt2800usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) +{ + struct hw_key_entry key_entry; + int timeout; + u32 offset; + + if (crypto->cmd == SET_KEY) { + /* + * 1 pairwise key is possible per AID, this means that the AID + * equals our hw_key_idx. Make sure the WCID starts _after_ the + * last possible shared key entry. + */ + if (crypto->aid > (256 - 32)) + return -ENOSPC; + + key->hw_key_idx = 32 + crypto->aid; + + memcpy(key_entry.key, crypto->key, + sizeof(key_entry.key)); + memcpy(key_entry.tx_mic, crypto->tx_mic, + sizeof(key_entry.tx_mic)); + memcpy(key_entry.rx_mic, crypto->rx_mic, + sizeof(key_entry.rx_mic)); + + offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); + timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); + rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, + offset, &key_entry, + sizeof(key_entry), + timeout); + } + + /* + * Update WCID information + */ + rt2800usb_config_wcid_attr(rt2x00dev, crypto, key); + + return 0; +} + +static void rt2800usb_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u32 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt2x00usb_register_read(rt2x00dev, RX_FILTER_CFG, ®); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CRC_ERROR, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST, + !(filter_flags & FIF_ALLMULTI)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BROADCAST, 0); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_DUPLICATE, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END_ACK, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_ACK, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CTS, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_RTS, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, + !(filter_flags & FIF_PSPOLL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 0); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, + !(filter_flags & FIF_CONTROL)); + rt2x00usb_register_write(rt2x00dev, RX_FILTER_CFG, reg); +} + +static void rt2800usb_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) +{ + unsigned int beacon_base; + u32 reg; + + if (flags & CONFIG_UPDATE_TYPE) { + /* + * Clear current synchronisation setup. + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); + rt2x00usb_register_write(rt2x00dev, beacon_base, 0); + + /* + * Enable synchronisation. + */ + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); + } + + if (flags & CONFIG_UPDATE_MAC) { + reg = le32_to_cpu(conf->mac[1]); + rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); + conf->mac[1] = cpu_to_le32(reg); + + rt2x00usb_register_multiwrite(rt2x00dev, MAC_ADDR_DW0, + conf->mac, sizeof(conf->mac)); + } + + if (flags & CONFIG_UPDATE_BSSID) { + reg = le32_to_cpu(conf->bssid[1]); + rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 0); + rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0); + conf->bssid[1] = cpu_to_le32(reg); + + rt2x00usb_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, + conf->bssid, sizeof(conf->bssid)); + } +} + +static void rt2800usb_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20); + rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, ®); + rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, + !!erp->short_preamble); + rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, + !!erp->short_preamble); + rt2x00usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, + erp->cts_protection ? 2 : 0); + rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, LEGACY_BASIC_RATE, + erp->basic_rates); + rt2x00usb_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); + + rt2x00usb_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); + rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); + rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); + rt2x00usb_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, XIFS_TIME_CFG, ®); + rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); + rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); + rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); + rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); + rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); + rt2x00usb_register_write(rt2x00dev, XIFS_TIME_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, + erp->beacon_int * 16); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); +} + +static void rt2800usb_config_ant(struct rt2x00_dev *rt2x00dev, + struct antenna_setup *ant) +{ + u8 r1; + u8 r3; + + rt2800usb_bbp_read(rt2x00dev, 1, &r1); + rt2800usb_bbp_read(rt2x00dev, 3, &r3); + + /* + * Configure the TX antenna. + */ + switch ((int)ant->tx) { + case 1: + rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); + break; + case 2: + rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); + break; + case 3: + /* Do nothing */ + break; + } + + /* + * Configure the RX antenna. + */ + switch ((int)ant->rx) { + case 1: + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); + break; + case 2: + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); + break; + case 3: + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); + break; + } + + rt2800usb_bbp_write(rt2x00dev, 3, r3); + rt2800usb_bbp_write(rt2x00dev, 1, r1); +} + +static void rt2800usb_config_lna_gain(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + u16 eeprom; + short lna_gain; + + if (libconf->rf.channel <= 14) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG); + } else if (libconf->rf.channel <= 64) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); + } else if (libconf->rf.channel <= 128) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); + } else { + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); + } + + rt2x00dev->lna_gain = lna_gain; +} + +static void rt2800usb_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); + + if (rt2x00dev->default_ant.tx == 1) + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); + + if (rt2x00dev->default_ant.rx == 1) { + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1); + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); + } else if (rt2x00dev->default_ant.rx == 2) + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); + + if (rf->channel > 14) { + /* + * When TX power is below 0, we should increase it by 7 to + * make it a positive value (Minumum value is -7). + * However this means that values between 0 and 7 have + * double meaning, and we should set a 7DBm boost flag. + */ + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, + (info->tx_power1 >= 0)); + + if (info->tx_power1 < 0) + info->tx_power1 += 7; + + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, + TXPOWER_A_TO_DEV(info->tx_power1)); + + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, + (info->tx_power2 >= 0)); + + if (info->tx_power2 < 0) + info->tx_power2 += 7; + + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, + TXPOWER_A_TO_DEV(info->tx_power2)); + } else { + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, + TXPOWER_G_TO_DEV(info->tx_power1)); + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, + TXPOWER_G_TO_DEV(info->tx_power2)); + } + + rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); + + rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); + rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); + rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); + rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); + + udelay(200); + + rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); + rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); + rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); + rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); + + udelay(200); + + rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); + rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); + rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); + rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); +} + +static void rt2800usb_config_channel_rt3x(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + u8 rfcsr; + + rt2800usb_rfcsr_write(rt2x00dev, 2, rf->rf1); + rt2800usb_rfcsr_write(rt2x00dev, 2, rf->rf3); + + rt2800usb_rfcsr_read(rt2x00dev, 6, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2); + rt2800usb_rfcsr_write(rt2x00dev, 6, rfcsr); + + rt2800usb_rfcsr_read(rt2x00dev, 12, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, + TXPOWER_G_TO_DEV(info->tx_power1)); + rt2800usb_rfcsr_write(rt2x00dev, 12, rfcsr); + + rt2800usb_rfcsr_read(rt2x00dev, 23, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); + rt2800usb_rfcsr_write(rt2x00dev, 23, rfcsr); + + rt2800usb_rfcsr_write(rt2x00dev, 24, + rt2x00dev->calibration[conf_is_ht40(conf)]); + + rt2800usb_rfcsr_read(rt2x00dev, 23, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); + rt2800usb_rfcsr_write(rt2x00dev, 23, rfcsr); +} + +static void rt2800usb_config_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + u32 reg; + unsigned int tx_pin; + u8 bbp; + + if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) + rt2800usb_config_channel_rt2x(rt2x00dev, conf, rf, info); + else + rt2800usb_config_channel_rt3x(rt2x00dev, conf, rf, info); + + /* + * Change BBP settings + */ + rt2800usb_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); + rt2800usb_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); + rt2800usb_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); + rt2800usb_bbp_write(rt2x00dev, 86, 0); + + if (rf->channel <= 14) { + if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { + rt2800usb_bbp_write(rt2x00dev, 82, 0x62); + rt2800usb_bbp_write(rt2x00dev, 75, 0x46); + } else { + rt2800usb_bbp_write(rt2x00dev, 82, 0x84); + rt2800usb_bbp_write(rt2x00dev, 75, 0x50); + } + } else { + rt2800usb_bbp_write(rt2x00dev, 82, 0xf2); + + if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) + rt2800usb_bbp_write(rt2x00dev, 75, 0x46); + else + rt2800usb_bbp_write(rt2x00dev, 75, 0x50); + } + + rt2x00usb_register_read(rt2x00dev, TX_BAND_CFG, ®); + rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); + rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14); + rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14); + rt2x00usb_register_write(rt2x00dev, TX_BAND_CFG, reg); + + tx_pin = 0; + + /* Turn on unused PA or LNA when not using 1T or 1R */ + if (rt2x00dev->default_ant.tx != 1) { + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); + } + + /* Turn on unused PA or LNA when not using 1T or 1R */ + if (rt2x00dev->default_ant.rx != 1) { + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); + } + + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14); + + rt2x00usb_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); + + rt2800usb_bbp_read(rt2x00dev, 4, &bbp); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); + rt2800usb_bbp_write(rt2x00dev, 4, bbp); + + rt2800usb_bbp_read(rt2x00dev, 3, &bbp); + rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); + rt2800usb_bbp_write(rt2x00dev, 3, bbp); + + if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { + if (conf_is_ht40(conf)) { + rt2800usb_bbp_write(rt2x00dev, 69, 0x1a); + rt2800usb_bbp_write(rt2x00dev, 70, 0x0a); + rt2800usb_bbp_write(rt2x00dev, 73, 0x16); + } else { + rt2800usb_bbp_write(rt2x00dev, 69, 0x16); + rt2800usb_bbp_write(rt2x00dev, 70, 0x08); + rt2800usb_bbp_write(rt2x00dev, 73, 0x11); + } + } + + msleep(1); +} + +static void rt2800usb_config_txpower(struct rt2x00_dev *rt2x00dev, + const int txpower) +{ + u32 reg; + u32 value = TXPOWER_G_TO_DEV(txpower); + u8 r1; + + rt2800usb_bbp_read(rt2x00dev, 1, &r1); + rt2x00_set_field8(®, BBP1_TX_POWER, 0); + rt2800usb_bbp_write(rt2x00dev, 1, r1); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_0, ®); + rt2x00_set_field32(®, TX_PWR_CFG_0_1MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_2MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_55MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_11MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_6MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_9MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_12MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_18MBS, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_0, reg); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_1, ®); + rt2x00_set_field32(®, TX_PWR_CFG_1_24MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_36MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_48MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_54MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS0, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS1, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS2, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS3, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_1, reg); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_2, ®); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS4, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS5, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS6, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS7, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS8, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS9, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS10, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS11, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_2, reg); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_3, ®); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS12, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS13, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS14, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS15, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN1, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN2, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN3, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN4, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_3, reg); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_4, ®); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN5, value); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN6, value); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN7, value); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN8, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_4, reg); +} + +static void rt2800usb_config_retry_limit(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, TX_RTY_CFG, ®); + rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, + libconf->conf->short_frame_max_tx_count); + rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, + libconf->conf->long_frame_max_tx_count); + rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); + rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); + rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); + rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); + rt2x00usb_register_write(rt2x00dev, TX_RTY_CFG, reg); +} + +static void rt2800usb_config_ps(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + enum dev_state state = + (libconf->conf->flags & IEEE80211_CONF_PS) ? + STATE_SLEEP : STATE_AWAKE; + u32 reg; + + if (state == STATE_SLEEP) { + rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); + + rt2x00usb_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, + libconf->conf->listen_interval - 1); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1); + rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); + + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); + } else { + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); + + rt2x00usb_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); + rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); + } +} + +static void rt2800usb_config(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf, + const unsigned int flags) +{ + /* Always recalculate LNA gain before changing configuration */ + rt2800usb_config_lna_gain(rt2x00dev, libconf); + + if (flags & IEEE80211_CONF_CHANGE_CHANNEL) + rt2800usb_config_channel(rt2x00dev, libconf->conf, + &libconf->rf, &libconf->channel); + if (flags & IEEE80211_CONF_CHANGE_POWER) + rt2800usb_config_txpower(rt2x00dev, libconf->conf->power_level); + if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) + rt2800usb_config_retry_limit(rt2x00dev, libconf); + if (flags & IEEE80211_CONF_CHANGE_PS) + rt2800usb_config_ps(rt2x00dev, libconf); +} + +/* + * Link tuning + */ +static void rt2800usb_link_stats(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) +{ + u32 reg; + + /* + * Update FCS error count from register. + */ + rt2x00usb_register_read(rt2x00dev, RX_STA_CNT0, ®); + qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR); +} + +static u8 rt2800usb_get_default_vgc(struct rt2x00_dev *rt2x00dev) +{ + if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { + if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) + return 0x1c + (2 * rt2x00dev->lna_gain); + else + return 0x2e + rt2x00dev->lna_gain; + } + + if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) + return 0x32 + (rt2x00dev->lna_gain * 5) / 3; + else + return 0x3a + (rt2x00dev->lna_gain * 5) / 3; +} + +static inline void rt2800usb_set_vgc(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, u8 vgc_level) +{ + if (qual->vgc_level != vgc_level) { + rt2800usb_bbp_write(rt2x00dev, 66, vgc_level); + qual->vgc_level = vgc_level; + qual->vgc_level_reg = vgc_level; + } +} + +static void rt2800usb_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) +{ + rt2800usb_set_vgc(rt2x00dev, qual, + rt2800usb_get_default_vgc(rt2x00dev)); +} + +static void rt2800usb_link_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count) +{ + if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) + return; + + /* + * When RSSI is better then -80 increase VGC level with 0x10 + */ + rt2800usb_set_vgc(rt2x00dev, qual, + rt2800usb_get_default_vgc(rt2x00dev) + + ((qual->rssi > -80) * 0x10)); +} + /* * Firmware functions */ @@ -153,7 +1172,7 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, * Wait for stable hardware. */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, MAC_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); if (reg && reg != ~0) break; msleep(1); @@ -173,8 +1192,8 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, data + offset, length, REGISTER_TIMEOUT32(length)); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); /* * Send firmware request to device to load firmware, @@ -189,18 +1208,18 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, } msleep(10); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); /* * Send signal to firmware during boot time. */ - rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); + rt2800usb_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); if ((chipset == 0x3070) || (chipset == 0x3071) || (chipset == 0x3572)) { udelay(200); - rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); + rt2800usb_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); udelay(10); } @@ -208,7 +1227,7 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, * Wait for device to stabilize. */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); + rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) break; msleep(1); @@ -222,13 +1241,535 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, /* * Initialize firmware. */ - rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); - rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + rt2x00usb_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); msleep(1); return 0; } +/* + * Initialization functions. + */ +static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + unsigned int i; + + /* + * Wait untill BBP and RF are ready. + */ + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); + if (reg && reg != ~0) + break; + msleep(1); + } + + if (i == REGISTER_BUSY_COUNT) { + ERROR(rt2x00dev, "Unstable hardware.\n"); + return -EBUSY; + } + + rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); + rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); + + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + + rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); + + rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, + USB_MODE_RESET, REGISTER_TIMEOUT); + + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + + rt2x00usb_register_read(rt2x00dev, BCN_OFFSET0, ®); + rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ + rt2x00_set_field32(®, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */ + rt2x00_set_field32(®, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */ + rt2x00_set_field32(®, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */ + rt2x00usb_register_write(rt2x00dev, BCN_OFFSET0, reg); + + rt2x00usb_register_read(rt2x00dev, BCN_OFFSET1, ®); + rt2x00_set_field32(®, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */ + rt2x00_set_field32(®, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */ + rt2x00_set_field32(®, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */ + rt2x00_set_field32(®, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */ + rt2x00usb_register_write(rt2x00dev, BCN_OFFSET1, reg); + + rt2x00usb_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); + rt2x00usb_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); + + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); + + if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); + } else { + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); + } + + rt2x00usb_register_read(rt2x00dev, TX_LINK_CFG, ®); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32); + rt2x00_set_field32(®, TX_LINK_CFG_MFB_ENABLE, 0); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0); + rt2x00_set_field32(®, TX_LINK_CFG_TX_MRQ_EN, 0); + rt2x00_set_field32(®, TX_LINK_CFG_TX_RDG_EN, 0); + rt2x00_set_field32(®, TX_LINK_CFG_TX_CF_ACK_EN, 1); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB, 0); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFS, 0); + rt2x00usb_register_write(rt2x00dev, TX_LINK_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10); + rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MAX_LEN_CFG, ®); + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); + if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION && + rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION) + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); + else + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); + rt2x00_set_field32(®, MAX_LEN_CFG_MIN_PSDU, 0); + rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0); + rt2x00usb_register_write(rt2x00dev, MAX_LEN_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f); + + rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, ®); + rt2x00_set_field32(®, AUTO_RSP_CFG_AUTORESPONDER, 1); + rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MMODE, 0); + rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MREF, 0); + rt2x00_set_field32(®, AUTO_RSP_CFG_DUAL_CTS_EN, 0); + rt2x00_set_field32(®, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0); + rt2x00usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, CCK_PROT_CFG, ®); + rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 8); + rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00usb_register_write(rt2x00dev, CCK_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 8); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MM20_PROT_CFG, ®); + rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_RATE, 0x4004); + rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0); + rt2x00usb_register_write(rt2x00dev, MM20_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MM40_PROT_CFG, ®); + rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084); + rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00usb_register_write(rt2x00dev, MM40_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, GF20_PROT_CFG, ®); + rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_RATE, 0x4004); + rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0); + rt2x00usb_register_write(rt2x00dev, GF20_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, GF40_PROT_CFG, ®); + rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_RATE, 0x4084); + rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00usb_register_write(rt2x00dev, GF40_PROT_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006); + + rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 3); + rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_BIG_ENDIAN, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_HDR_SEG_LEN, 0); + rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f); + rt2x00usb_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); + + rt2x00usb_register_read(rt2x00dev, TX_RTS_CFG, ®); + rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, + IEEE80211_MAX_RTS_THRESHOLD); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 0); + rt2x00usb_register_write(rt2x00dev, TX_RTS_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); + rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); + + /* + * ASIC will keep garbage value after boot, clear encryption keys. + */ + for (i = 0; i < 4; i++) + rt2x00usb_register_write(rt2x00dev, + SHARED_KEY_MODE_ENTRY(i), 0); + + for (i = 0; i < 256; i++) { + u32 wcid[2] = { 0xffffffff, 0x00ffffff }; + rt2x00usb_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), + wcid, sizeof(wcid)); + + rt2x00usb_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); + rt2x00usb_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); + } + + /* + * Clear all beacons + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE4, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE5, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE6, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE7, 0); + + rt2x00usb_register_read(rt2x00dev, USB_CYC_CFG, ®); + rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30); + rt2x00usb_register_write(rt2x00dev, USB_CYC_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, HT_FBK_CFG0, ®); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS0FBK, 0); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS1FBK, 0); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS2FBK, 1); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS3FBK, 2); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS4FBK, 3); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS5FBK, 4); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS6FBK, 5); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS7FBK, 6); + rt2x00usb_register_write(rt2x00dev, HT_FBK_CFG0, reg); + + rt2x00usb_register_read(rt2x00dev, HT_FBK_CFG1, ®); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS8FBK, 8); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS9FBK, 8); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS10FBK, 9); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS11FBK, 10); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS12FBK, 11); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS13FBK, 12); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS14FBK, 13); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS15FBK, 14); + rt2x00usb_register_write(rt2x00dev, HT_FBK_CFG1, reg); + + rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG0, ®); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 9); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 10); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 11); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 12); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS6FBK, 13); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS7FBK, 14); + rt2x00usb_register_write(rt2x00dev, LG_FBK_CFG0, reg); + + rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG1, ®); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS0FBK, 0); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS1FBK, 0); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS2FBK, 1); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS3FBK, 2); + rt2x00usb_register_write(rt2x00dev, LG_FBK_CFG1, reg); + + /* + * We must clear the error counters. + * These registers are cleared on read, + * so we may pass a useless variable to store the value. + */ + rt2x00usb_register_read(rt2x00dev, RX_STA_CNT0, ®); + rt2x00usb_register_read(rt2x00dev, RX_STA_CNT1, ®); + rt2x00usb_register_read(rt2x00dev, RX_STA_CNT2, ®); + rt2x00usb_register_read(rt2x00dev, TX_STA_CNT0, ®); + rt2x00usb_register_read(rt2x00dev, TX_STA_CNT1, ®); + rt2x00usb_register_read(rt2x00dev, TX_STA_CNT2, ®); + + return 0; +} + +static int rt2800usb_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u32 reg; + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00usb_register_read(rt2x00dev, MAC_STATUS_CFG, ®); + if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY)) + return 0; + + udelay(REGISTER_BUSY_DELAY); + } + + ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n"); + return -EACCES; +} + +static int rt2800usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u8 value; + + /* + * BBP was enabled after firmware was loaded, + * but we need to reactivate it now. + */ + rt2x00usb_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + msleep(1); + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2800usb_bbp_read(rt2x00dev, 0, &value); + if ((value != 0xff) && (value != 0x00)) + return 0; + udelay(REGISTER_BUSY_DELAY); + } + + ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); + return -EACCES; +} + +static int rt2800usb_init_bbp(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u16 eeprom; + u8 reg_id; + u8 value; + + if (unlikely(rt2800usb_wait_bbp_rf_ready(rt2x00dev) || + rt2800usb_wait_bbp_ready(rt2x00dev))) + return -EACCES; + + rt2800usb_bbp_write(rt2x00dev, 65, 0x2c); + rt2800usb_bbp_write(rt2x00dev, 66, 0x38); + rt2800usb_bbp_write(rt2x00dev, 69, 0x12); + rt2800usb_bbp_write(rt2x00dev, 70, 0x0a); + rt2800usb_bbp_write(rt2x00dev, 73, 0x10); + rt2800usb_bbp_write(rt2x00dev, 81, 0x37); + rt2800usb_bbp_write(rt2x00dev, 82, 0x62); + rt2800usb_bbp_write(rt2x00dev, 83, 0x6a); + rt2800usb_bbp_write(rt2x00dev, 84, 0x99); + rt2800usb_bbp_write(rt2x00dev, 86, 0x00); + rt2800usb_bbp_write(rt2x00dev, 91, 0x04); + rt2800usb_bbp_write(rt2x00dev, 92, 0x00); + rt2800usb_bbp_write(rt2x00dev, 103, 0x00); + rt2800usb_bbp_write(rt2x00dev, 105, 0x05); + + if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { + rt2800usb_bbp_write(rt2x00dev, 69, 0x16); + rt2800usb_bbp_write(rt2x00dev, 73, 0x12); + } + + if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) { + rt2800usb_bbp_write(rt2x00dev, 84, 0x19); + } + + if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { + rt2800usb_bbp_write(rt2x00dev, 70, 0x0a); + rt2800usb_bbp_write(rt2x00dev, 84, 0x99); + rt2800usb_bbp_write(rt2x00dev, 105, 0x05); + } + + for (i = 0; i < EEPROM_BBP_SIZE; i++) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); + + if (eeprom != 0xffff && eeprom != 0x0000) { + reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); + value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); + rt2800usb_bbp_write(rt2x00dev, reg_id, value); + } + } + + return 0; +} + +static u8 rt2800usb_init_rx_filter(struct rt2x00_dev *rt2x00dev, + bool bw40, u8 rfcsr24, u8 filter_target) +{ + unsigned int i; + u8 bbp; + u8 rfcsr; + u8 passband; + u8 stopband; + u8 overtuned = 0; + + rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24); + + rt2800usb_bbp_read(rt2x00dev, 4, &bbp); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40); + rt2800usb_bbp_write(rt2x00dev, 4, bbp); + + rt2800usb_rfcsr_read(rt2x00dev, 22, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1); + rt2800usb_rfcsr_write(rt2x00dev, 22, rfcsr); + + /* + * Set power & frequency of passband test tone + */ + rt2800usb_bbp_write(rt2x00dev, 24, 0); + + for (i = 0; i < 100; i++) { + rt2800usb_bbp_write(rt2x00dev, 25, 0x90); + msleep(1); + + rt2800usb_bbp_read(rt2x00dev, 55, &passband); + if (passband) + break; + } + + /* + * Set power & frequency of stopband test tone + */ + rt2800usb_bbp_write(rt2x00dev, 24, 0x06); + + for (i = 0; i < 100; i++) { + rt2800usb_bbp_write(rt2x00dev, 25, 0x90); + msleep(1); + + rt2800usb_bbp_read(rt2x00dev, 55, &stopband); + + if ((passband - stopband) <= filter_target) { + rfcsr24++; + overtuned += ((passband - stopband) == filter_target); + } else + break; + + rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24); + } + + rfcsr24 -= !!overtuned; + + rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24); + return rfcsr24; +} + +static int rt2800usb_init_rfcsr(struct rt2x00_dev *rt2x00dev) +{ + u8 rfcsr; + u8 bbp; + + if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) + return 0; + + /* + * Init RF calibration. + */ + rt2800usb_rfcsr_read(rt2x00dev, 30, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); + rt2800usb_rfcsr_write(rt2x00dev, 30, rfcsr); + msleep(1); + rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); + rt2800usb_rfcsr_write(rt2x00dev, 30, rfcsr); + + rt2800usb_rfcsr_write(rt2x00dev, 4, 0x40); + rt2800usb_rfcsr_write(rt2x00dev, 5, 0x03); + rt2800usb_rfcsr_write(rt2x00dev, 6, 0x02); + rt2800usb_rfcsr_write(rt2x00dev, 7, 0x70); + rt2800usb_rfcsr_write(rt2x00dev, 9, 0x0f); + rt2800usb_rfcsr_write(rt2x00dev, 10, 0x71); + rt2800usb_rfcsr_write(rt2x00dev, 11, 0x21); + rt2800usb_rfcsr_write(rt2x00dev, 12, 0x7b); + rt2800usb_rfcsr_write(rt2x00dev, 14, 0x90); + rt2800usb_rfcsr_write(rt2x00dev, 15, 0x58); + rt2800usb_rfcsr_write(rt2x00dev, 16, 0xb3); + rt2800usb_rfcsr_write(rt2x00dev, 17, 0x92); + rt2800usb_rfcsr_write(rt2x00dev, 18, 0x2c); + rt2800usb_rfcsr_write(rt2x00dev, 19, 0x02); + rt2800usb_rfcsr_write(rt2x00dev, 20, 0xba); + rt2800usb_rfcsr_write(rt2x00dev, 21, 0xdb); + rt2800usb_rfcsr_write(rt2x00dev, 24, 0x16); + rt2800usb_rfcsr_write(rt2x00dev, 25, 0x01); + rt2800usb_rfcsr_write(rt2x00dev, 27, 0x03); + rt2800usb_rfcsr_write(rt2x00dev, 29, 0x1f); + + /* + * Set RX Filter calibration for 20MHz and 40MHz + */ + rt2x00dev->calibration[0] = + rt2800usb_init_rx_filter(rt2x00dev, false, 0x07, 0x16); + rt2x00dev->calibration[1] = + rt2800usb_init_rx_filter(rt2x00dev, true, 0x27, 0x19); + + /* + * Set back to initial state + */ + rt2800usb_bbp_write(rt2x00dev, 24, 0); + + rt2800usb_rfcsr_read(rt2x00dev, 22, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0); + rt2800usb_rfcsr_write(rt2x00dev, 22, rfcsr); + + /* + * set BBP back to BW20 + */ + rt2800usb_bbp_read(rt2x00dev, 4, &bbp); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0); + rt2800usb_bbp_write(rt2x00dev, 4, bbp); + + return 0; +} + /* * Device state switch handlers. */ @@ -237,11 +1778,11 @@ static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, { u32 reg; - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, (state == STATE_RADIO_RX_ON) || (state == STATE_RADIO_RX_ON_LINK)); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); } static int rt2800usb_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) @@ -250,7 +1791,7 @@ static int rt2800usb_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) u32 reg; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) return 0; @@ -271,25 +1812,25 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) * Initialize all registers. */ if (unlikely(rt2800usb_wait_wpdma_ready(rt2x00dev) || - rt2800_init_registers(rt2x00dev) || - rt2800_init_bbp(rt2x00dev) || - rt2800_init_rfcsr(rt2x00dev))) + rt2800usb_init_registers(rt2x00dev) || + rt2800usb_init_bbp(rt2x00dev) || + rt2800usb_init_rfcsr(rt2x00dev))) return -EIO; - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); udelay(50); - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1); - rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); + rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, ®); rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); /* Don't use bulk in aggregation when working with USB 1.1 */ rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, @@ -303,26 +1844,26 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) ((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); - rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg); + rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg); - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); /* * Initialize LED control */ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff, + rt2800usb_mcu_request(rt2x00dev, MCU_LED_1, 0xff, word & 0xff, (word >> 8) & 0xff); rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff, + rt2800usb_mcu_request(rt2x00dev, MCU_LED_2, 0xff, word & 0xff, (word >> 8) & 0xff); rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff, + rt2800usb_mcu_request(rt2x00dev, MCU_LED_3, 0xff, word & 0xff, (word >> 8) & 0xff); return 0; @@ -332,14 +1873,14 @@ static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev) { u32 reg; - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); - rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0); - rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0); - rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0); + rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0); + rt2x00usb_register_write(rt2x00dev, TX_PIN_CFG, 0); /* Wait for DMA, ignore error */ rt2800usb_wait_wpdma_ready(rt2x00dev); @@ -351,9 +1892,9 @@ static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) { if (state == STATE_AWAKE) - rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); + rt2800usb_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); else - rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); + rt2800usb_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); return 0; } @@ -507,9 +2048,9 @@ static void rt2800usb_write_beacon(struct queue_entry *entry) * Disable beaconing while we are reloading the beacon data, * otherwise we might be sending out invalid data. */ - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); /* * Write entire beacon with descriptor to register. @@ -552,12 +2093,12 @@ static void rt2800usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, return; } - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) { rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); } } @@ -583,7 +2124,7 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, */ memcpy(skbdesc->desc, rxd, skbdesc->desc_len); rxd = (__le32 *)skbdesc->desc; - rxwi = &rxd[RXINFO_DESC_SIZE / sizeof(__le32)]; + rxwi = &rxd[RXD_DESC_SIZE / sizeof(__le32)]; /* * It is now safe to read the descriptor on all architectures. @@ -785,7 +2326,7 @@ static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev) * Identify RF chipset. */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); - rt2800_register_read(rt2x00dev, MAC_CSR0, ®); + rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2870, value, reg); /* @@ -844,9 +2385,9 @@ static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev) * Store led settings, for correct led behaviour. */ #ifdef CONFIG_RT2X00_LIB_LEDS - rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); - rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); + rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); + rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); + rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg); @@ -1059,25 +2600,10 @@ static int rt2800usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) return 0; } -static const struct rt2800_ops rt2800usb_rt2800_ops = { - .register_read = rt2x00usb_register_read, - .register_write = rt2x00usb_register_write, - .register_write_lock = rt2x00usb_register_write_lock, - - .register_multiread = rt2x00usb_register_multiread, - .register_multiwrite = rt2x00usb_register_multiwrite, - - .regbusy_read = rt2x00usb_regbusy_read, -}; - static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; - rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); - - rt2x00dev->priv = (void *)&rt2800usb_rt2800_ops; - /* * Allocate eeprom data. */ @@ -1119,6 +2645,162 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) return 0; } +/* + * IEEE80211 stack callback functions. + */ +static void rt2800usb_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, + u32 *iv32, u16 *iv16) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct mac_iveiv_entry iveiv_entry; + u32 offset; + + offset = MAC_IVEIV_ENTRY(hw_key_idx); + rt2x00usb_register_multiread(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); + + memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16)); + memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32)); +} + +static int rt2800usb_set_rts_threshold(struct ieee80211_hw *hw, u32 value) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + u32 reg; + bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD); + + rt2x00usb_register_read(rt2x00dev, TX_RTS_CFG, ®); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, value); + rt2x00usb_register_write(rt2x00dev, TX_RTS_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, CCK_PROT_CFG, ®); + rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, CCK_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); + rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MM20_PROT_CFG, ®); + rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, MM20_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MM40_PROT_CFG, ®); + rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, MM40_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, GF20_PROT_CFG, ®); + rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, GF20_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, GF40_PROT_CFG, ®); + rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, GF40_PROT_CFG, reg); + + return 0; +} + +static int rt2800usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, + const struct ieee80211_tx_queue_params *params) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct data_queue *queue; + struct rt2x00_field32 field; + int retval; + u32 reg; + u32 offset; + + /* + * First pass the configuration through rt2x00lib, that will + * update the queue settings and validate the input. After that + * we are free to update the registers based on the value + * in the queue parameter. + */ + retval = rt2x00mac_conf_tx(hw, queue_idx, params); + if (retval) + return retval; + + /* + * We only need to perform additional register initialization + * for WMM queues/ + */ + if (queue_idx >= 4) + return 0; + + queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); + + /* Update WMM TXOP register */ + offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2))); + field.bit_offset = (queue_idx & 1) * 16; + field.bit_mask = 0xffff << field.bit_offset; + + rt2x00usb_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, field, queue->txop); + rt2x00usb_register_write(rt2x00dev, offset, reg); + + /* Update WMM registers */ + field.bit_offset = queue_idx * 4; + field.bit_mask = 0xf << field.bit_offset; + + rt2x00usb_register_read(rt2x00dev, WMM_AIFSN_CFG, ®); + rt2x00_set_field32(®, field, queue->aifs); + rt2x00usb_register_write(rt2x00dev, WMM_AIFSN_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, WMM_CWMIN_CFG, ®); + rt2x00_set_field32(®, field, queue->cw_min); + rt2x00usb_register_write(rt2x00dev, WMM_CWMIN_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, WMM_CWMAX_CFG, ®); + rt2x00_set_field32(®, field, queue->cw_max); + rt2x00usb_register_write(rt2x00dev, WMM_CWMAX_CFG, reg); + + /* Update EDCA registers */ + offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx); + + rt2x00usb_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, EDCA_AC0_CFG_TX_OP, queue->txop); + rt2x00_set_field32(®, EDCA_AC0_CFG_AIFSN, queue->aifs); + rt2x00_set_field32(®, EDCA_AC0_CFG_CWMIN, queue->cw_min); + rt2x00_set_field32(®, EDCA_AC0_CFG_CWMAX, queue->cw_max); + rt2x00usb_register_write(rt2x00dev, offset, reg); + + return 0; +} + +static u64 rt2800usb_get_tsf(struct ieee80211_hw *hw) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + u64 tsf; + u32 reg; + + rt2x00usb_register_read(rt2x00dev, TSF_TIMER_DW1, ®); + tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32; + rt2x00usb_register_read(rt2x00dev, TSF_TIMER_DW0, ®); + tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD); + + return tsf; +} + +static const struct ieee80211_ops rt2800usb_mac80211_ops = { + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, + .remove_interface = rt2x00mac_remove_interface, + .config = rt2x00mac_config, + .configure_filter = rt2x00mac_configure_filter, + .set_tim = rt2x00mac_set_tim, + .set_key = rt2x00mac_set_key, + .get_stats = rt2x00mac_get_stats, + .get_tkip_seq = rt2800usb_get_tkip_seq, + .set_rts_threshold = rt2800usb_set_rts_threshold, + .bss_info_changed = rt2x00mac_bss_info_changed, + .conf_tx = rt2800usb_conf_tx, + .get_tx_stats = rt2x00mac_get_tx_stats, + .get_tsf = rt2800usb_get_tsf, + .rfkill_poll = rt2x00mac_rfkill_poll, +}; + static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .probe_hw = rt2800usb_probe_hw, .get_firmware_name = rt2800usb_get_firmware_name, @@ -1128,10 +2810,10 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .uninitialize = rt2x00usb_uninitialize, .clear_entry = rt2x00usb_clear_entry, .set_device_state = rt2800usb_set_device_state, - .rfkill_poll = rt2800_rfkill_poll, - .link_stats = rt2800_link_stats, - .reset_tuner = rt2800_reset_tuner, - .link_tuner = rt2800_link_tuner, + .rfkill_poll = rt2800usb_rfkill_poll, + .link_stats = rt2800usb_link_stats, + .reset_tuner = rt2800usb_reset_tuner, + .link_tuner = rt2800usb_link_tuner, .write_tx_desc = rt2800usb_write_tx_desc, .write_tx_data = rt2x00usb_write_tx_data, .write_beacon = rt2800usb_write_beacon, @@ -1139,19 +2821,19 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .kick_tx_queue = rt2800usb_kick_tx_queue, .kill_tx_queue = rt2x00usb_kill_tx_queue, .fill_rxdone = rt2800usb_fill_rxdone, - .config_shared_key = rt2800_config_shared_key, - .config_pairwise_key = rt2800_config_pairwise_key, - .config_filter = rt2800_config_filter, - .config_intf = rt2800_config_intf, - .config_erp = rt2800_config_erp, - .config_ant = rt2800_config_ant, - .config = rt2800_config, + .config_shared_key = rt2800usb_config_shared_key, + .config_pairwise_key = rt2800usb_config_pairwise_key, + .config_filter = rt2800usb_config_filter, + .config_intf = rt2800usb_config_intf, + .config_erp = rt2800usb_config_erp, + .config_ant = rt2800usb_config_ant, + .config = rt2800usb_config, }; static const struct data_queue_desc rt2800usb_queue_rx = { .entry_num = RX_ENTRIES, .data_size = AGGREGATION_SIZE, - .desc_size = RXINFO_DESC_SIZE + RXWI_DESC_SIZE, + .desc_size = RXD_DESC_SIZE + RXWI_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; @@ -1180,9 +2862,9 @@ static const struct rt2x00_ops rt2800usb_ops = { .tx = &rt2800usb_queue_tx, .bcn = &rt2800usb_queue_bcn, .lib = &rt2800usb_rt2x00_ops, - .hw = &rt2800_mac80211_ops, + .hw = &rt2800usb_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2800_rt2x00debug, + .debugfs = &rt2800usb_rt2x00debug, #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800usb.h b/trunk/drivers/net/wireless/rt2x00/rt2800usb.h index c9d7d40ee5fb..4d9991c9a51c 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2800usb.h @@ -27,42 +27,1444 @@ #ifndef RT2800USB_H #define RT2800USB_H +/* + * RF chip defines. + * + * RF2820 2.4G 2T3R + * RF2850 2.4G/5G 2T3R + * RF2720 2.4G 1T2R + * RF2750 2.4G/5G 1T2R + * RF3020 2.4G 1T1R + * RF2020 2.4G B/G + * RF3021 2.4G 1T2R + * RF3022 2.4G 2T2R + * RF3052 2.4G 2T2R + */ +#define RF2820 0x0001 +#define RF2850 0x0002 +#define RF2720 0x0003 +#define RF2750 0x0004 +#define RF3020 0x0005 +#define RF2020 0x0006 +#define RF3021 0x0007 +#define RF3022 0x0008 +#define RF3052 0x0009 + +/* + * RT2870 version + */ +#define RT2860C_VERSION 0x28600100 +#define RT2860D_VERSION 0x28600101 +#define RT2880E_VERSION 0x28720200 +#define RT2883_VERSION 0x28830300 +#define RT3070_VERSION 0x30700200 + +/* + * Signal information. + * Defaul offset is required for RSSI <-> dBm conversion. + */ +#define DEFAULT_RSSI_OFFSET 120 /* FIXME */ + +/* + * Register layout information. + */ +#define CSR_REG_BASE 0x1000 +#define CSR_REG_SIZE 0x0800 +#define EEPROM_BASE 0x0000 +#define EEPROM_SIZE 0x0110 +#define BBP_BASE 0x0000 +#define BBP_SIZE 0x0080 +#define RF_BASE 0x0004 +#define RF_SIZE 0x0010 + +/* + * Number of TX queues. + */ +#define NUM_TX_QUEUES 4 + /* * USB registers. */ /* - * USB_DMA_CFG - * RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns. - * RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes. - * PHY_CLEAR: phy watch dog enable. - * TX_CLEAR: Clear USB DMA TX path. - * TXOP_HALT: Halt TXOP count down when TX buffer is full. - * RX_BULK_AGG_EN: Enable Rx Bulk Aggregation. - * RX_BULK_EN: Enable USB DMA Rx. - * TX_BULK_EN: Enable USB DMA Tx. - * EP_OUT_VALID: OUT endpoint data valid. - * RX_BUSY: USB DMA RX FSM busy. - * TX_BUSY: USB DMA TX FSM busy. + * HOST-MCU shared memory + */ +#define HOST_CMD_CSR 0x0404 +#define HOST_CMD_CSR_HOST_COMMAND FIELD32(0x000000ff) + +/* + * INT_SOURCE_CSR: Interrupt source register. + * Write one to clear corresponding bit. + * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c + */ +#define INT_SOURCE_CSR 0x0200 +#define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001) +#define INT_SOURCE_CSR_TXDELAYINT FIELD32(0x00000002) +#define INT_SOURCE_CSR_RX_DONE FIELD32(0x00000004) +#define INT_SOURCE_CSR_AC0_DMA_DONE FIELD32(0x00000008) +#define INT_SOURCE_CSR_AC1_DMA_DONE FIELD32(0x00000010) +#define INT_SOURCE_CSR_AC2_DMA_DONE FIELD32(0x00000020) +#define INT_SOURCE_CSR_AC3_DMA_DONE FIELD32(0x00000040) +#define INT_SOURCE_CSR_HCCA_DMA_DONE FIELD32(0x00000080) +#define INT_SOURCE_CSR_MGMT_DMA_DONE FIELD32(0x00000100) +#define INT_SOURCE_CSR_MCU_COMMAND FIELD32(0x00000200) +#define INT_SOURCE_CSR_RXTX_COHERENT FIELD32(0x00000400) +#define INT_SOURCE_CSR_TBTT FIELD32(0x00000800) +#define INT_SOURCE_CSR_PRE_TBTT FIELD32(0x00001000) +#define INT_SOURCE_CSR_TX_FIFO_STATUS FIELD32(0x00002000) +#define INT_SOURCE_CSR_AUTO_WAKEUP FIELD32(0x00004000) +#define INT_SOURCE_CSR_GPTIMER FIELD32(0x00008000) +#define INT_SOURCE_CSR_RX_COHERENT FIELD32(0x00010000) +#define INT_SOURCE_CSR_TX_COHERENT FIELD32(0x00020000) + +/* + * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF. + */ +#define INT_MASK_CSR 0x0204 +#define INT_MASK_CSR_RXDELAYINT FIELD32(0x00000001) +#define INT_MASK_CSR_TXDELAYINT FIELD32(0x00000002) +#define INT_MASK_CSR_RX_DONE FIELD32(0x00000004) +#define INT_MASK_CSR_AC0_DMA_DONE FIELD32(0x00000008) +#define INT_MASK_CSR_AC1_DMA_DONE FIELD32(0x00000010) +#define INT_MASK_CSR_AC2_DMA_DONE FIELD32(0x00000020) +#define INT_MASK_CSR_AC3_DMA_DONE FIELD32(0x00000040) +#define INT_MASK_CSR_HCCA_DMA_DONE FIELD32(0x00000080) +#define INT_MASK_CSR_MGMT_DMA_DONE FIELD32(0x00000100) +#define INT_MASK_CSR_MCU_COMMAND FIELD32(0x00000200) +#define INT_MASK_CSR_RXTX_COHERENT FIELD32(0x00000400) +#define INT_MASK_CSR_TBTT FIELD32(0x00000800) +#define INT_MASK_CSR_PRE_TBTT FIELD32(0x00001000) +#define INT_MASK_CSR_TX_FIFO_STATUS FIELD32(0x00002000) +#define INT_MASK_CSR_AUTO_WAKEUP FIELD32(0x00004000) +#define INT_MASK_CSR_GPTIMER FIELD32(0x00008000) +#define INT_MASK_CSR_RX_COHERENT FIELD32(0x00010000) +#define INT_MASK_CSR_TX_COHERENT FIELD32(0x00020000) + +/* + * WPDMA_GLO_CFG + */ +#define WPDMA_GLO_CFG 0x0208 +#define WPDMA_GLO_CFG_ENABLE_TX_DMA FIELD32(0x00000001) +#define WPDMA_GLO_CFG_TX_DMA_BUSY FIELD32(0x00000002) +#define WPDMA_GLO_CFG_ENABLE_RX_DMA FIELD32(0x00000004) +#define WPDMA_GLO_CFG_RX_DMA_BUSY FIELD32(0x00000008) +#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE FIELD32(0x00000030) +#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE FIELD32(0x00000040) +#define WPDMA_GLO_CFG_BIG_ENDIAN FIELD32(0x00000080) +#define WPDMA_GLO_CFG_RX_HDR_SCATTER FIELD32(0x0000ff00) +#define WPDMA_GLO_CFG_HDR_SEG_LEN FIELD32(0xffff0000) + +/* + * WPDMA_RST_IDX + */ +#define WPDMA_RST_IDX 0x020c +#define WPDMA_RST_IDX_DTX_IDX0 FIELD32(0x00000001) +#define WPDMA_RST_IDX_DTX_IDX1 FIELD32(0x00000002) +#define WPDMA_RST_IDX_DTX_IDX2 FIELD32(0x00000004) +#define WPDMA_RST_IDX_DTX_IDX3 FIELD32(0x00000008) +#define WPDMA_RST_IDX_DTX_IDX4 FIELD32(0x00000010) +#define WPDMA_RST_IDX_DTX_IDX5 FIELD32(0x00000020) +#define WPDMA_RST_IDX_DRX_IDX0 FIELD32(0x00010000) + +/* + * DELAY_INT_CFG + */ +#define DELAY_INT_CFG 0x0210 +#define DELAY_INT_CFG_RXMAX_PTIME FIELD32(0x000000ff) +#define DELAY_INT_CFG_RXMAX_PINT FIELD32(0x00007f00) +#define DELAY_INT_CFG_RXDLY_INT_EN FIELD32(0x00008000) +#define DELAY_INT_CFG_TXMAX_PTIME FIELD32(0x00ff0000) +#define DELAY_INT_CFG_TXMAX_PINT FIELD32(0x7f000000) +#define DELAY_INT_CFG_TXDLY_INT_EN FIELD32(0x80000000) + +/* + * WMM_AIFSN_CFG: Aifsn for each EDCA AC + * AIFSN0: AC_BE + * AIFSN1: AC_BK + * AIFSN1: AC_VI + * AIFSN1: AC_VO + */ +#define WMM_AIFSN_CFG 0x0214 +#define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f) +#define WMM_AIFSN_CFG_AIFSN1 FIELD32(0x000000f0) +#define WMM_AIFSN_CFG_AIFSN2 FIELD32(0x00000f00) +#define WMM_AIFSN_CFG_AIFSN3 FIELD32(0x0000f000) + +/* + * WMM_CWMIN_CSR: CWmin for each EDCA AC + * CWMIN0: AC_BE + * CWMIN1: AC_BK + * CWMIN1: AC_VI + * CWMIN1: AC_VO + */ +#define WMM_CWMIN_CFG 0x0218 +#define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f) +#define WMM_CWMIN_CFG_CWMIN1 FIELD32(0x000000f0) +#define WMM_CWMIN_CFG_CWMIN2 FIELD32(0x00000f00) +#define WMM_CWMIN_CFG_CWMIN3 FIELD32(0x0000f000) + +/* + * WMM_CWMAX_CSR: CWmax for each EDCA AC + * CWMAX0: AC_BE + * CWMAX1: AC_BK + * CWMAX1: AC_VI + * CWMAX1: AC_VO + */ +#define WMM_CWMAX_CFG 0x021c +#define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f) +#define WMM_CWMAX_CFG_CWMAX1 FIELD32(0x000000f0) +#define WMM_CWMAX_CFG_CWMAX2 FIELD32(0x00000f00) +#define WMM_CWMAX_CFG_CWMAX3 FIELD32(0x0000f000) + +/* + * AC_TXOP0: AC_BK/AC_BE TXOP register + * AC0TXOP: AC_BK in unit of 32us + * AC1TXOP: AC_BE in unit of 32us + */ +#define WMM_TXOP0_CFG 0x0220 +#define WMM_TXOP0_CFG_AC0TXOP FIELD32(0x0000ffff) +#define WMM_TXOP0_CFG_AC1TXOP FIELD32(0xffff0000) + +/* + * AC_TXOP1: AC_VO/AC_VI TXOP register + * AC2TXOP: AC_VI in unit of 32us + * AC3TXOP: AC_VO in unit of 32us + */ +#define WMM_TXOP1_CFG 0x0224 +#define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff) +#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000) + +/* + * GPIO_CTRL_CFG: + */ +#define GPIO_CTRL_CFG 0x0228 +#define GPIO_CTRL_CFG_BIT0 FIELD32(0x00000001) +#define GPIO_CTRL_CFG_BIT1 FIELD32(0x00000002) +#define GPIO_CTRL_CFG_BIT2 FIELD32(0x00000004) +#define GPIO_CTRL_CFG_BIT3 FIELD32(0x00000008) +#define GPIO_CTRL_CFG_BIT4 FIELD32(0x00000010) +#define GPIO_CTRL_CFG_BIT5 FIELD32(0x00000020) +#define GPIO_CTRL_CFG_BIT6 FIELD32(0x00000040) +#define GPIO_CTRL_CFG_BIT7 FIELD32(0x00000080) +#define GPIO_CTRL_CFG_BIT8 FIELD32(0x00000100) + +/* + * MCU_CMD_CFG + */ +#define MCU_CMD_CFG 0x022c + +/* + * AC_BK register offsets + */ +#define TX_BASE_PTR0 0x0230 +#define TX_MAX_CNT0 0x0234 +#define TX_CTX_IDX0 0x0238 +#define TX_DTX_IDX0 0x023c + +/* + * AC_BE register offsets + */ +#define TX_BASE_PTR1 0x0240 +#define TX_MAX_CNT1 0x0244 +#define TX_CTX_IDX1 0x0248 +#define TX_DTX_IDX1 0x024c + +/* + * AC_VI register offsets + */ +#define TX_BASE_PTR2 0x0250 +#define TX_MAX_CNT2 0x0254 +#define TX_CTX_IDX2 0x0258 +#define TX_DTX_IDX2 0x025c + +/* + * AC_VO register offsets + */ +#define TX_BASE_PTR3 0x0260 +#define TX_MAX_CNT3 0x0264 +#define TX_CTX_IDX3 0x0268 +#define TX_DTX_IDX3 0x026c + +/* + * HCCA register offsets + */ +#define TX_BASE_PTR4 0x0270 +#define TX_MAX_CNT4 0x0274 +#define TX_CTX_IDX4 0x0278 +#define TX_DTX_IDX4 0x027c + +/* + * MGMT register offsets + */ +#define TX_BASE_PTR5 0x0280 +#define TX_MAX_CNT5 0x0284 +#define TX_CTX_IDX5 0x0288 +#define TX_DTX_IDX5 0x028c + +/* + * RX register offsets + */ +#define RX_BASE_PTR 0x0290 +#define RX_MAX_CNT 0x0294 +#define RX_CRX_IDX 0x0298 +#define RX_DRX_IDX 0x029c + +/* + * USB_DMA_CFG + * RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns. + * RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes. + * PHY_CLEAR: phy watch dog enable. + * TX_CLEAR: Clear USB DMA TX path. + * TXOP_HALT: Halt TXOP count down when TX buffer is full. + * RX_BULK_AGG_EN: Enable Rx Bulk Aggregation. + * RX_BULK_EN: Enable USB DMA Rx. + * TX_BULK_EN: Enable USB DMA Tx. + * EP_OUT_VALID: OUT endpoint data valid. + * RX_BUSY: USB DMA RX FSM busy. + * TX_BUSY: USB DMA TX FSM busy. + */ +#define USB_DMA_CFG 0x02a0 +#define USB_DMA_CFG_RX_BULK_AGG_TIMEOUT FIELD32(0x000000ff) +#define USB_DMA_CFG_RX_BULK_AGG_LIMIT FIELD32(0x0000ff00) +#define USB_DMA_CFG_PHY_CLEAR FIELD32(0x00010000) +#define USB_DMA_CFG_TX_CLEAR FIELD32(0x00080000) +#define USB_DMA_CFG_TXOP_HALT FIELD32(0x00100000) +#define USB_DMA_CFG_RX_BULK_AGG_EN FIELD32(0x00200000) +#define USB_DMA_CFG_RX_BULK_EN FIELD32(0x00400000) +#define USB_DMA_CFG_TX_BULK_EN FIELD32(0x00800000) +#define USB_DMA_CFG_EP_OUT_VALID FIELD32(0x3f000000) +#define USB_DMA_CFG_RX_BUSY FIELD32(0x40000000) +#define USB_DMA_CFG_TX_BUSY FIELD32(0x80000000) + +/* + * USB_CYC_CFG + */ +#define USB_CYC_CFG 0x02a4 +#define USB_CYC_CFG_CLOCK_CYCLE FIELD32(0x000000ff) + +/* + * PBF_SYS_CTRL + * HOST_RAM_WRITE: enable Host program ram write selection + */ +#define PBF_SYS_CTRL 0x0400 +#define PBF_SYS_CTRL_READY FIELD32(0x00000080) +#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) + +/* + * PBF registers + * Most are for debug. Driver doesn't touch PBF register. + */ +#define PBF_CFG 0x0408 +#define PBF_MAX_PCNT 0x040c +#define PBF_CTRL 0x0410 +#define PBF_INT_STA 0x0414 +#define PBF_INT_ENA 0x0418 + +/* + * BCN_OFFSET0: + */ +#define BCN_OFFSET0 0x042c +#define BCN_OFFSET0_BCN0 FIELD32(0x000000ff) +#define BCN_OFFSET0_BCN1 FIELD32(0x0000ff00) +#define BCN_OFFSET0_BCN2 FIELD32(0x00ff0000) +#define BCN_OFFSET0_BCN3 FIELD32(0xff000000) + +/* + * BCN_OFFSET1: + */ +#define BCN_OFFSET1 0x0430 +#define BCN_OFFSET1_BCN4 FIELD32(0x000000ff) +#define BCN_OFFSET1_BCN5 FIELD32(0x0000ff00) +#define BCN_OFFSET1_BCN6 FIELD32(0x00ff0000) +#define BCN_OFFSET1_BCN7 FIELD32(0xff000000) + +/* + * PBF registers + * Most are for debug. Driver doesn't touch PBF register. + */ +#define TXRXQ_PCNT 0x0438 +#define PBF_DBG 0x043c + +/* + * RF registers + */ +#define RF_CSR_CFG 0x0500 +#define RF_CSR_CFG_DATA FIELD32(0x000000ff) +#define RF_CSR_CFG_REGNUM FIELD32(0x00001f00) +#define RF_CSR_CFG_WRITE FIELD32(0x00010000) +#define RF_CSR_CFG_BUSY FIELD32(0x00020000) + +/* + * MAC Control/Status Registers(CSR). + * Some values are set in TU, whereas 1 TU == 1024 us. + */ + +/* + * MAC_CSR0: ASIC revision number. + * ASIC_REV: 0 + * ASIC_VER: 2870 + */ +#define MAC_CSR0 0x1000 +#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff) +#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000) + +/* + * MAC_SYS_CTRL: + */ +#define MAC_SYS_CTRL 0x1004 +#define MAC_SYS_CTRL_RESET_CSR FIELD32(0x00000001) +#define MAC_SYS_CTRL_RESET_BBP FIELD32(0x00000002) +#define MAC_SYS_CTRL_ENABLE_TX FIELD32(0x00000004) +#define MAC_SYS_CTRL_ENABLE_RX FIELD32(0x00000008) +#define MAC_SYS_CTRL_CONTINUOUS_TX FIELD32(0x00000010) +#define MAC_SYS_CTRL_LOOPBACK FIELD32(0x00000020) +#define MAC_SYS_CTRL_WLAN_HALT FIELD32(0x00000040) +#define MAC_SYS_CTRL_RX_TIMESTAMP FIELD32(0x00000080) + +/* + * MAC_ADDR_DW0: STA MAC register 0 + */ +#define MAC_ADDR_DW0 0x1008 +#define MAC_ADDR_DW0_BYTE0 FIELD32(0x000000ff) +#define MAC_ADDR_DW0_BYTE1 FIELD32(0x0000ff00) +#define MAC_ADDR_DW0_BYTE2 FIELD32(0x00ff0000) +#define MAC_ADDR_DW0_BYTE3 FIELD32(0xff000000) + +/* + * MAC_ADDR_DW1: STA MAC register 1 + * UNICAST_TO_ME_MASK: + * Used to mask off bits from byte 5 of the MAC address + * to determine the UNICAST_TO_ME bit for RX frames. + * The full mask is complemented by BSS_ID_MASK: + * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK + */ +#define MAC_ADDR_DW1 0x100c +#define MAC_ADDR_DW1_BYTE4 FIELD32(0x000000ff) +#define MAC_ADDR_DW1_BYTE5 FIELD32(0x0000ff00) +#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK FIELD32(0x00ff0000) + +/* + * MAC_BSSID_DW0: BSSID register 0 + */ +#define MAC_BSSID_DW0 0x1010 +#define MAC_BSSID_DW0_BYTE0 FIELD32(0x000000ff) +#define MAC_BSSID_DW0_BYTE1 FIELD32(0x0000ff00) +#define MAC_BSSID_DW0_BYTE2 FIELD32(0x00ff0000) +#define MAC_BSSID_DW0_BYTE3 FIELD32(0xff000000) + +/* + * MAC_BSSID_DW1: BSSID register 1 + * BSS_ID_MASK: + * 0: 1-BSSID mode (BSS index = 0) + * 1: 2-BSSID mode (BSS index: Byte5, bit 0) + * 2: 4-BSSID mode (BSS index: byte5, bit 0 - 1) + * 3: 8-BSSID mode (BSS index: byte5, bit 0 - 2) + * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the + * BSSID. This will make sure that those bits will be ignored + * when determining the MY_BSS of RX frames. + */ +#define MAC_BSSID_DW1 0x1014 +#define MAC_BSSID_DW1_BYTE4 FIELD32(0x000000ff) +#define MAC_BSSID_DW1_BYTE5 FIELD32(0x0000ff00) +#define MAC_BSSID_DW1_BSS_ID_MASK FIELD32(0x00030000) +#define MAC_BSSID_DW1_BSS_BCN_NUM FIELD32(0x001c0000) + +/* + * MAX_LEN_CFG: Maximum frame length register. + * MAX_MPDU: rt2860b max 16k bytes + * MAX_PSDU: Maximum PSDU length + * (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 + */ +#define MAX_LEN_CFG 0x1018 +#define MAX_LEN_CFG_MAX_MPDU FIELD32(0x00000fff) +#define MAX_LEN_CFG_MAX_PSDU FIELD32(0x00003000) +#define MAX_LEN_CFG_MIN_PSDU FIELD32(0x0000c000) +#define MAX_LEN_CFG_MIN_MPDU FIELD32(0x000f0000) + +/* + * BBP_CSR_CFG: BBP serial control register + * VALUE: Register value to program into BBP + * REG_NUM: Selected BBP register + * READ_CONTROL: 0 write BBP, 1 read BBP + * BUSY: ASIC is busy executing BBP commands + * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks + * BBP_RW_MODE: 0 serial, 1 paralell + */ +#define BBP_CSR_CFG 0x101c +#define BBP_CSR_CFG_VALUE FIELD32(0x000000ff) +#define BBP_CSR_CFG_REGNUM FIELD32(0x0000ff00) +#define BBP_CSR_CFG_READ_CONTROL FIELD32(0x00010000) +#define BBP_CSR_CFG_BUSY FIELD32(0x00020000) +#define BBP_CSR_CFG_BBP_PAR_DUR FIELD32(0x00040000) +#define BBP_CSR_CFG_BBP_RW_MODE FIELD32(0x00080000) + +/* + * RF_CSR_CFG0: RF control register + * REGID_AND_VALUE: Register value to program into RF + * BITWIDTH: Selected RF register + * STANDBYMODE: 0 high when standby, 1 low when standby + * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate + * BUSY: ASIC is busy executing RF commands + */ +#define RF_CSR_CFG0 0x1020 +#define RF_CSR_CFG0_REGID_AND_VALUE FIELD32(0x00ffffff) +#define RF_CSR_CFG0_BITWIDTH FIELD32(0x1f000000) +#define RF_CSR_CFG0_REG_VALUE_BW FIELD32(0x1fffffff) +#define RF_CSR_CFG0_STANDBYMODE FIELD32(0x20000000) +#define RF_CSR_CFG0_SEL FIELD32(0x40000000) +#define RF_CSR_CFG0_BUSY FIELD32(0x80000000) + +/* + * RF_CSR_CFG1: RF control register + * REGID_AND_VALUE: Register value to program into RF + * RFGAP: Gap between BB_CONTROL_RF and RF_LE + * 0: 3 system clock cycle (37.5usec) + * 1: 5 system clock cycle (62.5usec) + */ +#define RF_CSR_CFG1 0x1024 +#define RF_CSR_CFG1_REGID_AND_VALUE FIELD32(0x00ffffff) +#define RF_CSR_CFG1_RFGAP FIELD32(0x1f000000) + +/* + * RF_CSR_CFG2: RF control register + * VALUE: Register value to program into RF + * RFGAP: Gap between BB_CONTROL_RF and RF_LE + * 0: 3 system clock cycle (37.5usec) + * 1: 5 system clock cycle (62.5usec) + */ +#define RF_CSR_CFG2 0x1028 +#define RF_CSR_CFG2_VALUE FIELD32(0x00ffffff) + +/* + * LED_CFG: LED control + * color LED's: + * 0: off + * 1: blinking upon TX2 + * 2: periodic slow blinking + * 3: always on + * LED polarity: + * 0: active low + * 1: active high + */ +#define LED_CFG 0x102c +#define LED_CFG_ON_PERIOD FIELD32(0x000000ff) +#define LED_CFG_OFF_PERIOD FIELD32(0x0000ff00) +#define LED_CFG_SLOW_BLINK_PERIOD FIELD32(0x003f0000) +#define LED_CFG_R_LED_MODE FIELD32(0x03000000) +#define LED_CFG_G_LED_MODE FIELD32(0x0c000000) +#define LED_CFG_Y_LED_MODE FIELD32(0x30000000) +#define LED_CFG_LED_POLAR FIELD32(0x40000000) + +/* + * XIFS_TIME_CFG: MAC timing + * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX + * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX + * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX + * when MAC doesn't reference BBP signal BBRXEND + * EIFS: unit 1us + * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer + * + */ +#define XIFS_TIME_CFG 0x1100 +#define XIFS_TIME_CFG_CCKM_SIFS_TIME FIELD32(0x000000ff) +#define XIFS_TIME_CFG_OFDM_SIFS_TIME FIELD32(0x0000ff00) +#define XIFS_TIME_CFG_OFDM_XIFS_TIME FIELD32(0x000f0000) +#define XIFS_TIME_CFG_EIFS FIELD32(0x1ff00000) +#define XIFS_TIME_CFG_BB_RXEND_ENABLE FIELD32(0x20000000) + +/* + * BKOFF_SLOT_CFG: + */ +#define BKOFF_SLOT_CFG 0x1104 +#define BKOFF_SLOT_CFG_SLOT_TIME FIELD32(0x000000ff) +#define BKOFF_SLOT_CFG_CC_DELAY_TIME FIELD32(0x0000ff00) + +/* + * NAV_TIME_CFG: + */ +#define NAV_TIME_CFG 0x1108 +#define NAV_TIME_CFG_SIFS FIELD32(0x000000ff) +#define NAV_TIME_CFG_SLOT_TIME FIELD32(0x0000ff00) +#define NAV_TIME_CFG_EIFS FIELD32(0x01ff0000) +#define NAV_TIME_ZERO_SIFS FIELD32(0x02000000) + +/* + * CH_TIME_CFG: count as channel busy + */ +#define CH_TIME_CFG 0x110c + +/* + * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us + */ +#define PBF_LIFE_TIMER 0x1110 + +/* + * BCN_TIME_CFG: + * BEACON_INTERVAL: in unit of 1/16 TU + * TSF_TICKING: Enable TSF auto counting + * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode + * BEACON_GEN: Enable beacon generator + */ +#define BCN_TIME_CFG 0x1114 +#define BCN_TIME_CFG_BEACON_INTERVAL FIELD32(0x0000ffff) +#define BCN_TIME_CFG_TSF_TICKING FIELD32(0x00010000) +#define BCN_TIME_CFG_TSF_SYNC FIELD32(0x00060000) +#define BCN_TIME_CFG_TBTT_ENABLE FIELD32(0x00080000) +#define BCN_TIME_CFG_BEACON_GEN FIELD32(0x00100000) +#define BCN_TIME_CFG_TX_TIME_COMPENSATE FIELD32(0xf0000000) + +/* + * TBTT_SYNC_CFG: + */ +#define TBTT_SYNC_CFG 0x1118 + +/* + * TSF_TIMER_DW0: Local lsb TSF timer, read-only + */ +#define TSF_TIMER_DW0 0x111c +#define TSF_TIMER_DW0_LOW_WORD FIELD32(0xffffffff) + +/* + * TSF_TIMER_DW1: Local msb TSF timer, read-only + */ +#define TSF_TIMER_DW1 0x1120 +#define TSF_TIMER_DW1_HIGH_WORD FIELD32(0xffffffff) + +/* + * TBTT_TIMER: TImer remains till next TBTT, read-only + */ +#define TBTT_TIMER 0x1124 + +/* + * INT_TIMER_CFG: + */ +#define INT_TIMER_CFG 0x1128 + +/* + * INT_TIMER_EN: GP-timer and pre-tbtt Int enable + */ +#define INT_TIMER_EN 0x112c + +/* + * CH_IDLE_STA: channel idle time + */ +#define CH_IDLE_STA 0x1130 + +/* + * CH_BUSY_STA: channel busy time + */ +#define CH_BUSY_STA 0x1134 + +/* + * MAC_STATUS_CFG: + * BBP_RF_BUSY: When set to 0, BBP and RF are stable. + * if 1 or higher one of the 2 registers is busy. + */ +#define MAC_STATUS_CFG 0x1200 +#define MAC_STATUS_CFG_BBP_RF_BUSY FIELD32(0x00000003) + +/* + * PWR_PIN_CFG: + */ +#define PWR_PIN_CFG 0x1204 + +/* + * AUTOWAKEUP_CFG: Manual power control / status register + * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set + * AUTOWAKE: 0:sleep, 1:awake + */ +#define AUTOWAKEUP_CFG 0x1208 +#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME FIELD32(0x000000ff) +#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE FIELD32(0x00007f00) +#define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000) + +/* + * EDCA_AC0_CFG: + */ +#define EDCA_AC0_CFG 0x1300 +#define EDCA_AC0_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC0_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC0_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC0_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_AC1_CFG: + */ +#define EDCA_AC1_CFG 0x1304 +#define EDCA_AC1_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC1_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC1_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC1_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_AC2_CFG: + */ +#define EDCA_AC2_CFG 0x1308 +#define EDCA_AC2_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC2_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC2_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC2_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_AC3_CFG: + */ +#define EDCA_AC3_CFG 0x130c +#define EDCA_AC3_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC3_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC3_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC3_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_TID_AC_MAP: + */ +#define EDCA_TID_AC_MAP 0x1310 + +/* + * TX_PWR_CFG_0: + */ +#define TX_PWR_CFG_0 0x1314 +#define TX_PWR_CFG_0_1MBS FIELD32(0x0000000f) +#define TX_PWR_CFG_0_2MBS FIELD32(0x000000f0) +#define TX_PWR_CFG_0_55MBS FIELD32(0x00000f00) +#define TX_PWR_CFG_0_11MBS FIELD32(0x0000f000) +#define TX_PWR_CFG_0_6MBS FIELD32(0x000f0000) +#define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000) +#define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000) +#define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_1: + */ +#define TX_PWR_CFG_1 0x1318 +#define TX_PWR_CFG_1_24MBS FIELD32(0x0000000f) +#define TX_PWR_CFG_1_36MBS FIELD32(0x000000f0) +#define TX_PWR_CFG_1_48MBS FIELD32(0x00000f00) +#define TX_PWR_CFG_1_54MBS FIELD32(0x0000f000) +#define TX_PWR_CFG_1_MCS0 FIELD32(0x000f0000) +#define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000) +#define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000) +#define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_2: + */ +#define TX_PWR_CFG_2 0x131c +#define TX_PWR_CFG_2_MCS4 FIELD32(0x0000000f) +#define TX_PWR_CFG_2_MCS5 FIELD32(0x000000f0) +#define TX_PWR_CFG_2_MCS6 FIELD32(0x00000f00) +#define TX_PWR_CFG_2_MCS7 FIELD32(0x0000f000) +#define TX_PWR_CFG_2_MCS8 FIELD32(0x000f0000) +#define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000) +#define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000) +#define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_3: + */ +#define TX_PWR_CFG_3 0x1320 +#define TX_PWR_CFG_3_MCS12 FIELD32(0x0000000f) +#define TX_PWR_CFG_3_MCS13 FIELD32(0x000000f0) +#define TX_PWR_CFG_3_MCS14 FIELD32(0x00000f00) +#define TX_PWR_CFG_3_MCS15 FIELD32(0x0000f000) +#define TX_PWR_CFG_3_UKNOWN1 FIELD32(0x000f0000) +#define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000) +#define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000) +#define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_4: + */ +#define TX_PWR_CFG_4 0x1324 +#define TX_PWR_CFG_4_UKNOWN5 FIELD32(0x0000000f) +#define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0) +#define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00) +#define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000) + +/* + * TX_PIN_CFG: + */ +#define TX_PIN_CFG 0x1328 +#define TX_PIN_CFG_PA_PE_A0_EN FIELD32(0x00000001) +#define TX_PIN_CFG_PA_PE_G0_EN FIELD32(0x00000002) +#define TX_PIN_CFG_PA_PE_A1_EN FIELD32(0x00000004) +#define TX_PIN_CFG_PA_PE_G1_EN FIELD32(0x00000008) +#define TX_PIN_CFG_PA_PE_A0_POL FIELD32(0x00000010) +#define TX_PIN_CFG_PA_PE_G0_POL FIELD32(0x00000020) +#define TX_PIN_CFG_PA_PE_A1_POL FIELD32(0x00000040) +#define TX_PIN_CFG_PA_PE_G1_POL FIELD32(0x00000080) +#define TX_PIN_CFG_LNA_PE_A0_EN FIELD32(0x00000100) +#define TX_PIN_CFG_LNA_PE_G0_EN FIELD32(0x00000200) +#define TX_PIN_CFG_LNA_PE_A1_EN FIELD32(0x00000400) +#define TX_PIN_CFG_LNA_PE_G1_EN FIELD32(0x00000800) +#define TX_PIN_CFG_LNA_PE_A0_POL FIELD32(0x00001000) +#define TX_PIN_CFG_LNA_PE_G0_POL FIELD32(0x00002000) +#define TX_PIN_CFG_LNA_PE_A1_POL FIELD32(0x00004000) +#define TX_PIN_CFG_LNA_PE_G1_POL FIELD32(0x00008000) +#define TX_PIN_CFG_RFTR_EN FIELD32(0x00010000) +#define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000) +#define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000) +#define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000) + +/* + * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz + */ +#define TX_BAND_CFG 0x132c +#define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001) +#define TX_BAND_CFG_A FIELD32(0x00000002) +#define TX_BAND_CFG_BG FIELD32(0x00000004) + +/* + * TX_SW_CFG0: + */ +#define TX_SW_CFG0 0x1330 + +/* + * TX_SW_CFG1: + */ +#define TX_SW_CFG1 0x1334 + +/* + * TX_SW_CFG2: + */ +#define TX_SW_CFG2 0x1338 + +/* + * TXOP_THRES_CFG: + */ +#define TXOP_THRES_CFG 0x133c + +/* + * TXOP_CTRL_CFG: + */ +#define TXOP_CTRL_CFG 0x1340 + +/* + * TX_RTS_CFG: + * RTS_THRES: unit:byte + * RTS_FBK_EN: enable rts rate fallback + */ +#define TX_RTS_CFG 0x1344 +#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT FIELD32(0x000000ff) +#define TX_RTS_CFG_RTS_THRES FIELD32(0x00ffff00) +#define TX_RTS_CFG_RTS_FBK_EN FIELD32(0x01000000) + +/* + * TX_TIMEOUT_CFG: + * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us + * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure + * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation. + * it is recommended that: + * (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) + */ +#define TX_TIMEOUT_CFG 0x1348 +#define TX_TIMEOUT_CFG_MPDU_LIFETIME FIELD32(0x000000f0) +#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT FIELD32(0x0000ff00) +#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT FIELD32(0x00ff0000) + +/* + * TX_RTY_CFG: + * SHORT_RTY_LIMIT: short retry limit + * LONG_RTY_LIMIT: long retry limit + * LONG_RTY_THRE: Long retry threshoold + * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode + * 0:expired by retry limit, 1: expired by mpdu life timer + * AGG_RTY_MODE: Aggregate MPDU retry mode + * 0:expired by retry limit, 1: expired by mpdu life timer + * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable + */ +#define TX_RTY_CFG 0x134c +#define TX_RTY_CFG_SHORT_RTY_LIMIT FIELD32(0x000000ff) +#define TX_RTY_CFG_LONG_RTY_LIMIT FIELD32(0x0000ff00) +#define TX_RTY_CFG_LONG_RTY_THRE FIELD32(0x0fff0000) +#define TX_RTY_CFG_NON_AGG_RTY_MODE FIELD32(0x10000000) +#define TX_RTY_CFG_AGG_RTY_MODE FIELD32(0x20000000) +#define TX_RTY_CFG_TX_AUTO_FB_ENABLE FIELD32(0x40000000) + +/* + * TX_LINK_CFG: + * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us + * MFB_ENABLE: TX apply remote MFB 1:enable + * REMOTE_UMFS_ENABLE: remote unsolicit MFB enable + * 0: not apply remote remote unsolicit (MFS=7) + * TX_MRQ_EN: MCS request TX enable + * TX_RDG_EN: RDG TX enable + * TX_CF_ACK_EN: Piggyback CF-ACK enable + * REMOTE_MFB: remote MCS feedback + * REMOTE_MFS: remote MCS feedback sequence number + */ +#define TX_LINK_CFG 0x1350 +#define TX_LINK_CFG_REMOTE_MFB_LIFETIME FIELD32(0x000000ff) +#define TX_LINK_CFG_MFB_ENABLE FIELD32(0x00000100) +#define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200) +#define TX_LINK_CFG_TX_MRQ_EN FIELD32(0x00000400) +#define TX_LINK_CFG_TX_RDG_EN FIELD32(0x00000800) +#define TX_LINK_CFG_TX_CF_ACK_EN FIELD32(0x00001000) +#define TX_LINK_CFG_REMOTE_MFB FIELD32(0x00ff0000) +#define TX_LINK_CFG_REMOTE_MFS FIELD32(0xff000000) + +/* + * HT_FBK_CFG0: + */ +#define HT_FBK_CFG0 0x1354 +#define HT_FBK_CFG0_HTMCS0FBK FIELD32(0x0000000f) +#define HT_FBK_CFG0_HTMCS1FBK FIELD32(0x000000f0) +#define HT_FBK_CFG0_HTMCS2FBK FIELD32(0x00000f00) +#define HT_FBK_CFG0_HTMCS3FBK FIELD32(0x0000f000) +#define HT_FBK_CFG0_HTMCS4FBK FIELD32(0x000f0000) +#define HT_FBK_CFG0_HTMCS5FBK FIELD32(0x00f00000) +#define HT_FBK_CFG0_HTMCS6FBK FIELD32(0x0f000000) +#define HT_FBK_CFG0_HTMCS7FBK FIELD32(0xf0000000) + +/* + * HT_FBK_CFG1: + */ +#define HT_FBK_CFG1 0x1358 +#define HT_FBK_CFG1_HTMCS8FBK FIELD32(0x0000000f) +#define HT_FBK_CFG1_HTMCS9FBK FIELD32(0x000000f0) +#define HT_FBK_CFG1_HTMCS10FBK FIELD32(0x00000f00) +#define HT_FBK_CFG1_HTMCS11FBK FIELD32(0x0000f000) +#define HT_FBK_CFG1_HTMCS12FBK FIELD32(0x000f0000) +#define HT_FBK_CFG1_HTMCS13FBK FIELD32(0x00f00000) +#define HT_FBK_CFG1_HTMCS14FBK FIELD32(0x0f000000) +#define HT_FBK_CFG1_HTMCS15FBK FIELD32(0xf0000000) + +/* + * LG_FBK_CFG0: + */ +#define LG_FBK_CFG0 0x135c +#define LG_FBK_CFG0_OFDMMCS0FBK FIELD32(0x0000000f) +#define LG_FBK_CFG0_OFDMMCS1FBK FIELD32(0x000000f0) +#define LG_FBK_CFG0_OFDMMCS2FBK FIELD32(0x00000f00) +#define LG_FBK_CFG0_OFDMMCS3FBK FIELD32(0x0000f000) +#define LG_FBK_CFG0_OFDMMCS4FBK FIELD32(0x000f0000) +#define LG_FBK_CFG0_OFDMMCS5FBK FIELD32(0x00f00000) +#define LG_FBK_CFG0_OFDMMCS6FBK FIELD32(0x0f000000) +#define LG_FBK_CFG0_OFDMMCS7FBK FIELD32(0xf0000000) + +/* + * LG_FBK_CFG1: + */ +#define LG_FBK_CFG1 0x1360 +#define LG_FBK_CFG0_CCKMCS0FBK FIELD32(0x0000000f) +#define LG_FBK_CFG0_CCKMCS1FBK FIELD32(0x000000f0) +#define LG_FBK_CFG0_CCKMCS2FBK FIELD32(0x00000f00) +#define LG_FBK_CFG0_CCKMCS3FBK FIELD32(0x0000f000) + +/* + * CCK_PROT_CFG: CCK Protection + * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd) + * PROTECT_CTRL: Protection control frame type for CCK TX + * 0:none, 1:RTS/CTS, 2:CTS-to-self + * PROTECT_NAV: TXOP protection type for CCK TX + * 0:none, 1:ShortNAVprotect, 2:LongNAVProtect + * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow + * RTS_TH_EN: RTS threshold enable on CCK TX + */ +#define CCK_PROT_CFG 0x1364 +#define CCK_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define CCK_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define CCK_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define CCK_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define CCK_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define CCK_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define CCK_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define CCK_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define CCK_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define CCK_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * OFDM_PROT_CFG: OFDM Protection + */ +#define OFDM_PROT_CFG 0x1368 +#define OFDM_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define OFDM_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define OFDM_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define OFDM_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * MM20_PROT_CFG: MM20 Protection + */ +#define MM20_PROT_CFG 0x136c +#define MM20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define MM20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define MM20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define MM20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define MM20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define MM20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define MM20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * MM40_PROT_CFG: MM40 Protection + */ +#define MM40_PROT_CFG 0x1370 +#define MM40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define MM40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define MM40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define MM40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define MM40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define MM40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define MM40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * GF20_PROT_CFG: GF20 Protection + */ +#define GF20_PROT_CFG 0x1374 +#define GF20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define GF20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define GF20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define GF20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define GF20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define GF20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define GF20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * GF40_PROT_CFG: GF40 Protection + */ +#define GF40_PROT_CFG 0x1378 +#define GF40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define GF40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define GF40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define GF40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define GF40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define GF40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define GF40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * EXP_CTS_TIME: + */ +#define EXP_CTS_TIME 0x137c + +/* + * EXP_ACK_TIME: + */ +#define EXP_ACK_TIME 0x1380 + +/* + * RX_FILTER_CFG: RX configuration register. + */ +#define RX_FILTER_CFG 0x1400 +#define RX_FILTER_CFG_DROP_CRC_ERROR FIELD32(0x00000001) +#define RX_FILTER_CFG_DROP_PHY_ERROR FIELD32(0x00000002) +#define RX_FILTER_CFG_DROP_NOT_TO_ME FIELD32(0x00000004) +#define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008) +#define RX_FILTER_CFG_DROP_VER_ERROR FIELD32(0x00000010) +#define RX_FILTER_CFG_DROP_MULTICAST FIELD32(0x00000020) +#define RX_FILTER_CFG_DROP_BROADCAST FIELD32(0x00000040) +#define RX_FILTER_CFG_DROP_DUPLICATE FIELD32(0x00000080) +#define RX_FILTER_CFG_DROP_CF_END_ACK FIELD32(0x00000100) +#define RX_FILTER_CFG_DROP_CF_END FIELD32(0x00000200) +#define RX_FILTER_CFG_DROP_ACK FIELD32(0x00000400) +#define RX_FILTER_CFG_DROP_CTS FIELD32(0x00000800) +#define RX_FILTER_CFG_DROP_RTS FIELD32(0x00001000) +#define RX_FILTER_CFG_DROP_PSPOLL FIELD32(0x00002000) +#define RX_FILTER_CFG_DROP_BA FIELD32(0x00004000) +#define RX_FILTER_CFG_DROP_BAR FIELD32(0x00008000) +#define RX_FILTER_CFG_DROP_CNTL FIELD32(0x00010000) + +/* + * AUTO_RSP_CFG: + * AUTORESPONDER: 0: disable, 1: enable + * BAC_ACK_POLICY: 0:long, 1:short preamble + * CTS_40_MMODE: Response CTS 40MHz duplicate mode + * CTS_40_MREF: Response CTS 40MHz duplicate mode + * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble + * DUAL_CTS_EN: Power bit value in control frame + * ACK_CTS_PSM_BIT:Power bit value in control frame + */ +#define AUTO_RSP_CFG 0x1404 +#define AUTO_RSP_CFG_AUTORESPONDER FIELD32(0x00000001) +#define AUTO_RSP_CFG_BAC_ACK_POLICY FIELD32(0x00000002) +#define AUTO_RSP_CFG_CTS_40_MMODE FIELD32(0x00000004) +#define AUTO_RSP_CFG_CTS_40_MREF FIELD32(0x00000008) +#define AUTO_RSP_CFG_AR_PREAMBLE FIELD32(0x00000010) +#define AUTO_RSP_CFG_DUAL_CTS_EN FIELD32(0x00000040) +#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT FIELD32(0x00000080) + +/* + * LEGACY_BASIC_RATE: + */ +#define LEGACY_BASIC_RATE 0x1408 + +/* + * HT_BASIC_RATE: + */ +#define HT_BASIC_RATE 0x140c + +/* + * HT_CTRL_CFG: + */ +#define HT_CTRL_CFG 0x1410 + +/* + * SIFS_COST_CFG: + */ +#define SIFS_COST_CFG 0x1414 + +/* + * RX_PARSER_CFG: + * Set NAV for all received frames + */ +#define RX_PARSER_CFG 0x1418 + +/* + * TX_SEC_CNT0: + */ +#define TX_SEC_CNT0 0x1500 + +/* + * RX_SEC_CNT0: + */ +#define RX_SEC_CNT0 0x1504 + +/* + * CCMP_FC_MUTE: + */ +#define CCMP_FC_MUTE 0x1508 + +/* + * TXOP_HLDR_ADDR0: + */ +#define TXOP_HLDR_ADDR0 0x1600 + +/* + * TXOP_HLDR_ADDR1: + */ +#define TXOP_HLDR_ADDR1 0x1604 + +/* + * TXOP_HLDR_ET: + */ +#define TXOP_HLDR_ET 0x1608 + +/* + * QOS_CFPOLL_RA_DW0: + */ +#define QOS_CFPOLL_RA_DW0 0x160c + +/* + * QOS_CFPOLL_RA_DW1: + */ +#define QOS_CFPOLL_RA_DW1 0x1610 + +/* + * QOS_CFPOLL_QC: + */ +#define QOS_CFPOLL_QC 0x1614 + +/* + * RX_STA_CNT0: RX PLCP error count & RX CRC error count + */ +#define RX_STA_CNT0 0x1700 +#define RX_STA_CNT0_CRC_ERR FIELD32(0x0000ffff) +#define RX_STA_CNT0_PHY_ERR FIELD32(0xffff0000) + +/* + * RX_STA_CNT1: RX False CCA count & RX LONG frame count + */ +#define RX_STA_CNT1 0x1704 +#define RX_STA_CNT1_FALSE_CCA FIELD32(0x0000ffff) +#define RX_STA_CNT1_PLCP_ERR FIELD32(0xffff0000) + +/* + * RX_STA_CNT2: + */ +#define RX_STA_CNT2 0x1708 +#define RX_STA_CNT2_RX_DUPLI_COUNT FIELD32(0x0000ffff) +#define RX_STA_CNT2_RX_FIFO_OVERFLOW FIELD32(0xffff0000) + +/* + * TX_STA_CNT0: TX Beacon count + */ +#define TX_STA_CNT0 0x170c +#define TX_STA_CNT0_TX_FAIL_COUNT FIELD32(0x0000ffff) +#define TX_STA_CNT0_TX_BEACON_COUNT FIELD32(0xffff0000) + +/* + * TX_STA_CNT1: TX tx count + */ +#define TX_STA_CNT1 0x1710 +#define TX_STA_CNT1_TX_SUCCESS FIELD32(0x0000ffff) +#define TX_STA_CNT1_TX_RETRANSMIT FIELD32(0xffff0000) + +/* + * TX_STA_CNT2: TX tx count + */ +#define TX_STA_CNT2 0x1714 +#define TX_STA_CNT2_TX_ZERO_LEN_COUNT FIELD32(0x0000ffff) +#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) + +/* + * TX_STA_FIFO: TX Result for specific PID status fifo register + */ +#define TX_STA_FIFO 0x1718 +#define TX_STA_FIFO_VALID FIELD32(0x00000001) +#define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e) +#define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020) +#define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040) +#define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080) +#define TX_STA_FIFO_WCID FIELD32(0x0000ff00) +#define TX_STA_FIFO_SUCCESS_RATE FIELD32(0xffff0000) + +/* + * TX_AGG_CNT: Debug counter + */ +#define TX_AGG_CNT 0x171c +#define TX_AGG_CNT_NON_AGG_TX_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT_AGG_TX_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT0: + */ +#define TX_AGG_CNT0 0x1720 +#define TX_AGG_CNT0_AGG_SIZE_1_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT0_AGG_SIZE_2_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT1: + */ +#define TX_AGG_CNT1 0x1724 +#define TX_AGG_CNT1_AGG_SIZE_3_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT1_AGG_SIZE_4_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT2: */ -#define USB_DMA_CFG 0x02a0 -#define USB_DMA_CFG_RX_BULK_AGG_TIMEOUT FIELD32(0x000000ff) -#define USB_DMA_CFG_RX_BULK_AGG_LIMIT FIELD32(0x0000ff00) -#define USB_DMA_CFG_PHY_CLEAR FIELD32(0x00010000) -#define USB_DMA_CFG_TX_CLEAR FIELD32(0x00080000) -#define USB_DMA_CFG_TXOP_HALT FIELD32(0x00100000) -#define USB_DMA_CFG_RX_BULK_AGG_EN FIELD32(0x00200000) -#define USB_DMA_CFG_RX_BULK_EN FIELD32(0x00400000) -#define USB_DMA_CFG_TX_BULK_EN FIELD32(0x00800000) -#define USB_DMA_CFG_EP_OUT_VALID FIELD32(0x3f000000) -#define USB_DMA_CFG_RX_BUSY FIELD32(0x40000000) -#define USB_DMA_CFG_TX_BUSY FIELD32(0x80000000) +#define TX_AGG_CNT2 0x1728 +#define TX_AGG_CNT2_AGG_SIZE_5_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT2_AGG_SIZE_6_COUNT FIELD32(0xffff0000) /* - * USB_CYC_CFG + * TX_AGG_CNT3: */ -#define USB_CYC_CFG 0x02a4 -#define USB_CYC_CFG_CLOCK_CYCLE FIELD32(0x000000ff) +#define TX_AGG_CNT3 0x172c +#define TX_AGG_CNT3_AGG_SIZE_7_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT3_AGG_SIZE_8_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT4: + */ +#define TX_AGG_CNT4 0x1730 +#define TX_AGG_CNT4_AGG_SIZE_9_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT4_AGG_SIZE_10_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT5: + */ +#define TX_AGG_CNT5 0x1734 +#define TX_AGG_CNT5_AGG_SIZE_11_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT5_AGG_SIZE_12_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT6: + */ +#define TX_AGG_CNT6 0x1738 +#define TX_AGG_CNT6_AGG_SIZE_13_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT6_AGG_SIZE_14_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT7: + */ +#define TX_AGG_CNT7 0x173c +#define TX_AGG_CNT7_AGG_SIZE_15_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT7_AGG_SIZE_16_COUNT FIELD32(0xffff0000) + +/* + * MPDU_DENSITY_CNT: + * TX_ZERO_DEL: TX zero length delimiter count + * RX_ZERO_DEL: RX zero length delimiter count + */ +#define MPDU_DENSITY_CNT 0x1740 +#define MPDU_DENSITY_CNT_TX_ZERO_DEL FIELD32(0x0000ffff) +#define MPDU_DENSITY_CNT_RX_ZERO_DEL FIELD32(0xffff0000) + +/* + * Security key table memory. + * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry + * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry + * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry + * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry + * SHARED_KEY_TABLE_BASE: 32 bytes * 32-entry + * SHARED_KEY_MODE_BASE: 4 bits * 32-entry + */ +#define MAC_WCID_BASE 0x1800 +#define PAIRWISE_KEY_TABLE_BASE 0x4000 +#define MAC_IVEIV_TABLE_BASE 0x6000 +#define MAC_WCID_ATTRIBUTE_BASE 0x6800 +#define SHARED_KEY_TABLE_BASE 0x6c00 +#define SHARED_KEY_MODE_BASE 0x7000 + +#define MAC_WCID_ENTRY(__idx) \ + ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) ) +#define PAIRWISE_KEY_ENTRY(__idx) \ + ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) +#define MAC_IVEIV_ENTRY(__idx) \ + ( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) ) +#define MAC_WCID_ATTR_ENTRY(__idx) \ + ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) +#define SHARED_KEY_ENTRY(__idx) \ + ( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) +#define SHARED_KEY_MODE_ENTRY(__idx) \ + ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) ) + +struct mac_wcid_entry { + u8 mac[6]; + u8 reserved[2]; +} __attribute__ ((packed)); + +struct hw_key_entry { + u8 key[16]; + u8 tx_mic[8]; + u8 rx_mic[8]; +} __attribute__ ((packed)); + +struct mac_iveiv_entry { + u8 iv[8]; +} __attribute__ ((packed)); + +/* + * MAC_WCID_ATTRIBUTE: + */ +#define MAC_WCID_ATTRIBUTE_KEYTAB FIELD32(0x00000001) +#define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e) +#define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) +#define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) + +/* + * SHARED_KEY_MODE: + */ +#define SHARED_KEY_MODE_BSS0_KEY0 FIELD32(0x00000007) +#define SHARED_KEY_MODE_BSS0_KEY1 FIELD32(0x00000070) +#define SHARED_KEY_MODE_BSS0_KEY2 FIELD32(0x00000700) +#define SHARED_KEY_MODE_BSS0_KEY3 FIELD32(0x00007000) +#define SHARED_KEY_MODE_BSS1_KEY0 FIELD32(0x00070000) +#define SHARED_KEY_MODE_BSS1_KEY1 FIELD32(0x00700000) +#define SHARED_KEY_MODE_BSS1_KEY2 FIELD32(0x07000000) +#define SHARED_KEY_MODE_BSS1_KEY3 FIELD32(0x70000000) + +/* + * HOST-MCU communication + */ + +/* + * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. + */ +#define H2M_MAILBOX_CSR 0x7010 +#define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff) +#define H2M_MAILBOX_CSR_ARG1 FIELD32(0x0000ff00) +#define H2M_MAILBOX_CSR_CMD_TOKEN FIELD32(0x00ff0000) +#define H2M_MAILBOX_CSR_OWNER FIELD32(0xff000000) + +/* + * H2M_MAILBOX_CID: + */ +#define H2M_MAILBOX_CID 0x7014 +#define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff) +#define H2M_MAILBOX_CID_CMD1 FIELD32(0x0000ff00) +#define H2M_MAILBOX_CID_CMD2 FIELD32(0x00ff0000) +#define H2M_MAILBOX_CID_CMD3 FIELD32(0xff000000) + +/* + * H2M_MAILBOX_STATUS: + */ +#define H2M_MAILBOX_STATUS 0x701c + +/* + * H2M_INT_SRC: + */ +#define H2M_INT_SRC 0x7024 + +/* + * H2M_BBP_AGENT: + */ +#define H2M_BBP_AGENT 0x7028 + +/* + * MCU_LEDCS: LED control for MCU Mailbox. + */ +#define MCU_LEDCS_LED_MODE FIELD8(0x1f) +#define MCU_LEDCS_POLARITY FIELD8(0x01) + +/* + * HW_CS_CTS_BASE: + * Carrier-sense CTS frame base address. + * It's where mac stores carrier-sense frame for carrier-sense function. + */ +#define HW_CS_CTS_BASE 0x7700 + +/* + * HW_DFS_CTS_BASE: + * FS CTS frame base address. It's where mac stores CTS frame for DFS. + */ +#define HW_DFS_CTS_BASE 0x7780 + +/* + * TXRX control registers - base address 0x3000 + */ + +/* + * TXRX_CSR1: + * rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. + */ +#define TXRX_CSR1 0x77d0 + +/* + * HW_DEBUG_SETTING_BASE: + * since NULL frame won't be that long (256 byte) + * We steal 16 tail bytes to save debugging settings + */ +#define HW_DEBUG_SETTING_BASE 0x77f0 +#define HW_DEBUG_SETTING_BASE2 0x7770 + +/* + * HW_BEACON_BASE + * In order to support maximum 8 MBSS and its maximum length + * is 512 bytes for each beacon + * Three section discontinue memory segments will be used. + * 1. The original region for BCN 0~3 + * 2. Extract memory from FCE table for BCN 4~5 + * 3. Extract memory from Pair-wise key table for BCN 6~7 + * It occupied those memory of wcid 238~253 for BCN 6 + * and wcid 222~237 for BCN 7 + * + * IMPORTANT NOTE: Not sure why legacy driver does this, + * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6. + */ +#define HW_BEACON_BASE0 0x7800 +#define HW_BEACON_BASE1 0x7a00 +#define HW_BEACON_BASE2 0x7c00 +#define HW_BEACON_BASE3 0x7e00 +#define HW_BEACON_BASE4 0x7200 +#define HW_BEACON_BASE5 0x7400 +#define HW_BEACON_BASE6 0x5dc0 +#define HW_BEACON_BASE7 0x5bc0 + +#define HW_BEACON_OFFSET(__index) \ + ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \ + (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \ + (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) ) /* * 8051 firmware image. @@ -70,11 +1472,319 @@ #define FIRMWARE_RT2870 "rt2870.bin" #define FIRMWARE_IMAGE_BASE 0x3000 +/* + * BBP registers. + * The wordsize of the BBP is 8 bits. + */ + +/* + * BBP 1: TX Antenna + */ +#define BBP1_TX_POWER FIELD8(0x07) +#define BBP1_TX_ANTENNA FIELD8(0x18) + +/* + * BBP 3: RX Antenna + */ +#define BBP3_RX_ANTENNA FIELD8(0x18) +#define BBP3_HT40_PLUS FIELD8(0x20) + +/* + * BBP 4: Bandwidth + */ +#define BBP4_TX_BF FIELD8(0x01) +#define BBP4_BANDWIDTH FIELD8(0x18) + +/* + * RFCSR registers + * The wordsize of the RFCSR is 8 bits. + */ + +/* + * RFCSR 6: + */ +#define RFCSR6_R FIELD8(0x03) + +/* + * RFCSR 7: + */ +#define RFCSR7_RF_TUNING FIELD8(0x01) + +/* + * RFCSR 12: + */ +#define RFCSR12_TX_POWER FIELD8(0x1f) + +/* + * RFCSR 22: + */ +#define RFCSR22_BASEBAND_LOOPBACK FIELD8(0x01) + +/* + * RFCSR 23: + */ +#define RFCSR23_FREQ_OFFSET FIELD8(0x7f) + +/* + * RFCSR 30: + */ +#define RFCSR30_RF_CALIBRATION FIELD8(0x80) + +/* + * RF registers + */ + +/* + * RF 2 + */ +#define RF2_ANTENNA_RX2 FIELD32(0x00000040) +#define RF2_ANTENNA_TX1 FIELD32(0x00004000) +#define RF2_ANTENNA_RX1 FIELD32(0x00020000) + +/* + * RF 3 + */ +#define RF3_TXPOWER_G FIELD32(0x00003e00) +#define RF3_TXPOWER_A_7DBM_BOOST FIELD32(0x00000200) +#define RF3_TXPOWER_A FIELD32(0x00003c00) + +/* + * RF 4 + */ +#define RF4_TXPOWER_G FIELD32(0x000007c0) +#define RF4_TXPOWER_A_7DBM_BOOST FIELD32(0x00000040) +#define RF4_TXPOWER_A FIELD32(0x00000780) +#define RF4_FREQ_OFFSET FIELD32(0x001f8000) +#define RF4_HT40 FIELD32(0x00200000) + +/* + * EEPROM content. + * The wordsize of the EEPROM is 16 bits. + */ + +/* + * EEPROM Version + */ +#define EEPROM_VERSION 0x0001 +#define EEPROM_VERSION_FAE FIELD16(0x00ff) +#define EEPROM_VERSION_VERSION FIELD16(0xff00) + +/* + * HW MAC address. + */ +#define EEPROM_MAC_ADDR_0 0x0002 +#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) +#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) +#define EEPROM_MAC_ADDR_1 0x0003 +#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) +#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) +#define EEPROM_MAC_ADDR_2 0x0004 +#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) +#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) + +/* + * EEPROM ANTENNA config + * RXPATH: 1: 1R, 2: 2R, 3: 3R + * TXPATH: 1: 1T, 2: 2T + */ +#define EEPROM_ANTENNA 0x001a +#define EEPROM_ANTENNA_RXPATH FIELD16(0x000f) +#define EEPROM_ANTENNA_TXPATH FIELD16(0x00f0) +#define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0f00) + +/* + * EEPROM NIC config + * CARDBUS_ACCEL: 0 - enable, 1 - disable + */ +#define EEPROM_NIC 0x001b +#define EEPROM_NIC_HW_RADIO FIELD16(0x0001) +#define EEPROM_NIC_DYNAMIC_TX_AGC FIELD16(0x0002) +#define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0004) +#define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0008) +#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0010) +#define EEPROM_NIC_BW40M_SB_BG FIELD16(0x0020) +#define EEPROM_NIC_BW40M_SB_A FIELD16(0x0040) +#define EEPROM_NIC_WPS_PBC FIELD16(0x0080) +#define EEPROM_NIC_BW40M_BG FIELD16(0x0100) +#define EEPROM_NIC_BW40M_A FIELD16(0x0200) + +/* + * EEPROM frequency + */ +#define EEPROM_FREQ 0x001d +#define EEPROM_FREQ_OFFSET FIELD16(0x00ff) +#define EEPROM_FREQ_LED_MODE FIELD16(0x7f00) +#define EEPROM_FREQ_LED_POLARITY FIELD16(0x1000) + +/* + * EEPROM LED + * POLARITY_RDY_G: Polarity RDY_G setting. + * POLARITY_RDY_A: Polarity RDY_A setting. + * POLARITY_ACT: Polarity ACT setting. + * POLARITY_GPIO_0: Polarity GPIO0 setting. + * POLARITY_GPIO_1: Polarity GPIO1 setting. + * POLARITY_GPIO_2: Polarity GPIO2 setting. + * POLARITY_GPIO_3: Polarity GPIO3 setting. + * POLARITY_GPIO_4: Polarity GPIO4 setting. + * LED_MODE: Led mode. + */ +#define EEPROM_LED1 0x001e +#define EEPROM_LED2 0x001f +#define EEPROM_LED3 0x0020 +#define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001) +#define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002) +#define EEPROM_LED_POLARITY_ACT FIELD16(0x0004) +#define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008) +#define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010) +#define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020) +#define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040) +#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080) +#define EEPROM_LED_LED_MODE FIELD16(0x1f00) + +/* + * EEPROM LNA + */ +#define EEPROM_LNA 0x0022 +#define EEPROM_LNA_BG FIELD16(0x00ff) +#define EEPROM_LNA_A0 FIELD16(0xff00) + +/* + * EEPROM RSSI BG offset + */ +#define EEPROM_RSSI_BG 0x0023 +#define EEPROM_RSSI_BG_OFFSET0 FIELD16(0x00ff) +#define EEPROM_RSSI_BG_OFFSET1 FIELD16(0xff00) + +/* + * EEPROM RSSI BG2 offset + */ +#define EEPROM_RSSI_BG2 0x0024 +#define EEPROM_RSSI_BG2_OFFSET2 FIELD16(0x00ff) +#define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00) + +/* + * EEPROM RSSI A offset + */ +#define EEPROM_RSSI_A 0x0025 +#define EEPROM_RSSI_A_OFFSET0 FIELD16(0x00ff) +#define EEPROM_RSSI_A_OFFSET1 FIELD16(0xff00) + +/* + * EEPROM RSSI A2 offset + */ +#define EEPROM_RSSI_A2 0x0026 +#define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff) +#define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) + +/* + * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power. + * This is delta in 40MHZ. + * VALUE: Tx Power dalta value (MAX=4) + * TYPE: 1: Plus the delta value, 0: minus the delta value + * TXPOWER: Enable: + */ +#define EEPROM_TXPOWER_DELTA 0x0028 +#define EEPROM_TXPOWER_DELTA_VALUE FIELD16(0x003f) +#define EEPROM_TXPOWER_DELTA_TYPE FIELD16(0x0040) +#define EEPROM_TXPOWER_DELTA_TXPOWER FIELD16(0x0080) + +/* + * EEPROM TXPOWER 802.11BG + */ +#define EEPROM_TXPOWER_BG1 0x0029 +#define EEPROM_TXPOWER_BG2 0x0030 +#define EEPROM_TXPOWER_BG_SIZE 7 +#define EEPROM_TXPOWER_BG_1 FIELD16(0x00ff) +#define EEPROM_TXPOWER_BG_2 FIELD16(0xff00) + +/* + * EEPROM TXPOWER 802.11A + */ +#define EEPROM_TXPOWER_A1 0x003c +#define EEPROM_TXPOWER_A2 0x0053 +#define EEPROM_TXPOWER_A_SIZE 6 +#define EEPROM_TXPOWER_A_1 FIELD16(0x00ff) +#define EEPROM_TXPOWER_A_2 FIELD16(0xff00) + +/* + * EEPROM TXpower byrate: 20MHZ power + */ +#define EEPROM_TXPOWER_BYRATE 0x006f + +/* + * EEPROM BBP. + */ +#define EEPROM_BBP_START 0x0078 +#define EEPROM_BBP_SIZE 16 +#define EEPROM_BBP_VALUE FIELD16(0x00ff) +#define EEPROM_BBP_REG_ID FIELD16(0xff00) + +/* + * MCU mailbox commands. + */ +#define MCU_SLEEP 0x30 +#define MCU_WAKEUP 0x31 +#define MCU_RADIO_OFF 0x35 +#define MCU_CURRENT 0x36 +#define MCU_LED 0x50 +#define MCU_LED_STRENGTH 0x51 +#define MCU_LED_1 0x52 +#define MCU_LED_2 0x53 +#define MCU_LED_3 0x54 +#define MCU_RADAR 0x60 +#define MCU_BOOT_SIGNAL 0x72 +#define MCU_BBP_SIGNAL 0x80 +#define MCU_POWER_SAVE 0x83 + +/* + * MCU mailbox tokens + */ +#define TOKEN_WAKUP 3 + /* * DMA descriptor defines. */ +#define TXD_DESC_SIZE ( 4 * sizeof(__le32) ) #define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) -#define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) +#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) ) +#define RXD_DESC_SIZE ( 1 * sizeof(__le32) ) +#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) + +/* + * TX descriptor format for TX, PRIO and Beacon Ring. + */ + +/* + * Word0 + */ +#define TXD_W0_SD_PTR0 FIELD32(0xffffffff) + +/* + * Word1 + */ +#define TXD_W1_SD_LEN1 FIELD32(0x00003fff) +#define TXD_W1_LAST_SEC1 FIELD32(0x00004000) +#define TXD_W1_BURST FIELD32(0x00008000) +#define TXD_W1_SD_LEN0 FIELD32(0x3fff0000) +#define TXD_W1_LAST_SEC0 FIELD32(0x40000000) +#define TXD_W1_DMA_DONE FIELD32(0x80000000) + +/* + * Word2 + */ +#define TXD_W2_SD_PTR1 FIELD32(0xffffffff) + +/* + * Word3 + * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI + * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. + * 0:MGMT, 1:HCCA 2:EDCA + */ +#define TXD_W3_WIV FIELD32(0x01000000) +#define TXD_W3_QSEL FIELD32(0x06000000) +#define TXD_W3_TCO FIELD32(0x20000000) +#define TXD_W3_UCO FIELD32(0x40000000) +#define TXD_W3_ICO FIELD32(0x80000000) /* * TX Info structure @@ -96,6 +1806,52 @@ #define TXINFO_W0_USB_DMA_NEXT_VALID FIELD32(0x40000000) #define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000) +/* + * TX WI structure + */ + +/* + * Word0 + * FRAG: 1 To inform TKIP engine this is a fragment. + * MIMO_PS: The remote peer is in dynamic MIMO-PS mode + * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs + * BW: Channel bandwidth 20MHz or 40 MHz + * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED + */ +#define TXWI_W0_FRAG FIELD32(0x00000001) +#define TXWI_W0_MIMO_PS FIELD32(0x00000002) +#define TXWI_W0_CF_ACK FIELD32(0x00000004) +#define TXWI_W0_TS FIELD32(0x00000008) +#define TXWI_W0_AMPDU FIELD32(0x00000010) +#define TXWI_W0_MPDU_DENSITY FIELD32(0x000000e0) +#define TXWI_W0_TX_OP FIELD32(0x00000300) +#define TXWI_W0_MCS FIELD32(0x007f0000) +#define TXWI_W0_BW FIELD32(0x00800000) +#define TXWI_W0_SHORT_GI FIELD32(0x01000000) +#define TXWI_W0_STBC FIELD32(0x06000000) +#define TXWI_W0_IFS FIELD32(0x08000000) +#define TXWI_W0_PHYMODE FIELD32(0xc0000000) + +/* + * Word1 + */ +#define TXWI_W1_ACK FIELD32(0x00000001) +#define TXWI_W1_NSEQ FIELD32(0x00000002) +#define TXWI_W1_BW_WIN_SIZE FIELD32(0x000000fc) +#define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00) +#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) +#define TXWI_W1_PACKETID FIELD32(0xf0000000) + +/* + * Word2 + */ +#define TXWI_W2_IV FIELD32(0xffffffff) + +/* + * Word3 + */ +#define TXWI_W3_EIV FIELD32(0xffffffff) + /* * RX descriptor format for RX Ring. */ @@ -132,4 +1888,64 @@ #define RXD_W0_LAST_AMSDU FIELD32(0x00080000) #define RXD_W0_PLCP_SIGNAL FIELD32(0xfff00000) +/* + * RX WI structure + */ + +/* + * Word0 + */ +#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff) +#define RXWI_W0_KEY_INDEX FIELD32(0x00000300) +#define RXWI_W0_BSSID FIELD32(0x00001c00) +#define RXWI_W0_UDF FIELD32(0x0000e000) +#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) +#define RXWI_W0_TID FIELD32(0xf0000000) + +/* + * Word1 + */ +#define RXWI_W1_FRAG FIELD32(0x0000000f) +#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0) +#define RXWI_W1_MCS FIELD32(0x007f0000) +#define RXWI_W1_BW FIELD32(0x00800000) +#define RXWI_W1_SHORT_GI FIELD32(0x01000000) +#define RXWI_W1_STBC FIELD32(0x06000000) +#define RXWI_W1_PHYMODE FIELD32(0xc0000000) + +/* + * Word2 + */ +#define RXWI_W2_RSSI0 FIELD32(0x000000ff) +#define RXWI_W2_RSSI1 FIELD32(0x0000ff00) +#define RXWI_W2_RSSI2 FIELD32(0x00ff0000) + +/* + * Word3 + */ +#define RXWI_W3_SNR0 FIELD32(0x000000ff) +#define RXWI_W3_SNR1 FIELD32(0x0000ff00) + +/* + * Macros for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. + */ +#define MIN_G_TXPOWER 0 +#define MIN_A_TXPOWER -7 +#define MAX_G_TXPOWER 31 +#define MAX_A_TXPOWER 15 +#define DEFAULT_TXPOWER 5 + +#define TXPOWER_G_FROM_DEV(__txpower) \ + ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) + +#define TXPOWER_G_TO_DEV(__txpower) \ + clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER) + +#define TXPOWER_A_FROM_DEV(__txpower) \ + ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) + +#define TXPOWER_A_TO_DEV(__txpower) \ + clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER) + #endif /* RT2800USB_H */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00.h b/trunk/drivers/net/wireless/rt2x00/rt2x00.h index c83dbaefd57a..196de8ab8153 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00.h @@ -144,11 +144,6 @@ struct avg_val { int avg_weight; }; -enum rt2x00_chip_intf { - RT2X00_CHIP_INTF_PCI, - RT2X00_CHIP_INTF_USB, -}; - /* * Chipset identification * The chipset on the device is composed of a RT and RF chip. @@ -174,8 +169,6 @@ struct rt2x00_chip { u16 rf; u32 rev; - - enum rt2x00_chip_intf intf; }; /* @@ -849,22 +842,8 @@ struct rt2x00_dev { * Firmware image. */ const struct firmware *fw; - - /* - * Driver specific data. - */ - void *priv; }; -/* - * Register defines. - * Some registers require multiple attempts before success, - * in those cases REGISTER_BUSY_COUNT attempts should be - * taken with a REGISTER_BUSY_DELAY interval. - */ -#define REGISTER_BUSY_COUNT 5 -#define REGISTER_BUSY_DELAY 100 - /* * Generic RF access. * The RF is being accessed by word index. @@ -953,28 +932,6 @@ static inline bool rt2x00_check_rev(const struct rt2x00_chip *chipset, return ((chipset->rev & mask) == rev); } -static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, - enum rt2x00_chip_intf intf) -{ - rt2x00dev->chip.intf = intf; -} - -static inline bool rt2x00_intf(const struct rt2x00_chip *chipset, - enum rt2x00_chip_intf intf) -{ - return (chipset->intf == intf); -} - -static inline bool rt2x00_intf_is_pci(struct rt2x00_dev *rt2x00dev) -{ - return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_PCI); -} - -static inline bool rt2x00_intf_is_usb(struct rt2x00_dev *rt2x00dev) -{ - return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_USB); -} - /** * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. * @rt2x00dev: Pointer to &struct rt2x00_dev. diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c index 73bbec58341e..71761b343839 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -815,8 +815,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) mutex_init(&rt2x00dev->csr_mutex); - set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); - /* * Make room for rt2x00_intf inside the per-interface * structure ieee80211_vif. @@ -873,6 +871,8 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) rt2x00leds_register(rt2x00dev); rt2x00debug_register(rt2x00dev); + set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); + return 0; exit: diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00leds.h b/trunk/drivers/net/wireless/rt2x00/rt2x00leds.h index 8e03c045e037..1046977e6a12 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00leds.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00leds.h @@ -33,6 +33,8 @@ enum led_type { LED_TYPE_QUALITY, }; +#ifdef CONFIG_RT2X00_LIB_LEDS + struct rt2x00_led { struct rt2x00_dev *rt2x00dev; struct led_classdev led_dev; @@ -43,4 +45,6 @@ struct rt2x00_led { #define LED_REGISTERED ( 1 << 1 ) }; +#endif /* CONFIG_RT2X00_LIB_LEDS */ + #endif /* RT2X00LEDS_H */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00link.c b/trunk/drivers/net/wireless/rt2x00/rt2x00link.c index c708d0be9155..c64db0ba7f40 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00link.c @@ -362,9 +362,8 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) rt2x00link_reset_tuner(rt2x00dev, false); - if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - ieee80211_queue_delayed_work(rt2x00dev->hw, - &link->work, LINK_TUNE_INTERVAL); + ieee80211_queue_delayed_work(rt2x00dev->hw, + &link->work, LINK_TUNE_INTERVAL); } void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) @@ -470,10 +469,8 @@ static void rt2x00link_tuner(struct work_struct *work) * Increase tuner counter, and reschedule the next link tuner run. */ link->count++; - - if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - ieee80211_queue_delayed_work(rt2x00dev->hw, - &link->work, LINK_TUNE_INTERVAL); + ieee80211_queue_delayed_work(rt2x00dev->hw, + &link->work, LINK_TUNE_INTERVAL); } void rt2x00link_register(struct rt2x00_dev *rt2x00dev) diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h index ae33eebe9a6f..15a12487e04b 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -34,6 +34,15 @@ */ #define PCI_DEVICE_DATA(__ops) .driver_data = (kernel_ulong_t)(__ops) +/* + * Register defines. + * Some registers require multiple attempts before success, + * in those cases REGISTER_BUSY_COUNT attempts should be + * taken with a REGISTER_BUSY_DELAY interval. + */ +#define REGISTER_BUSY_COUNT 5 +#define REGISTER_BUSY_DELAY 100 + /* * Register access. */ @@ -44,9 +53,10 @@ static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev, *value = readl(rt2x00dev->csr.base + offset); } -static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - void *value, const u32 length) +static inline void +rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + void *value, const u16 length) { memcpy_fromio(value, rt2x00dev->csr.base + offset, length); } @@ -58,10 +68,10 @@ static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev, writel(value, rt2x00dev->csr.base + offset); } -static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - const void *value, - const u32 length) +static inline void +rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + const void *value, const u16 length) { memcpy_toio(rt2x00dev->csr.base + offset, value, length); } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c index c9cbdaa1073f..501544882c2c 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -47,8 +47,6 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, (requesttype == USB_VENDOR_REQUEST_IN) ? usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0); - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - return -ENODEV; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { status = usb_control_msg(usb_dev, pipe, request, requesttype, @@ -62,10 +60,8 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, * -ENODEV: Device has disappeared, no point continuing. * All other errors: Try again. */ - else if (status == -ENODEV) { - clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); + else if (status == -ENODEV) break; - } } ERROR(rt2x00dev, @@ -160,14 +156,11 @@ EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_large_buff); int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, const unsigned int offset, - const struct rt2x00_field32 field, + struct rt2x00_field32 field, u32 *reg) { unsigned int i; - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - return -ENODEV; - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2x00usb_register_read_lock(rt2x00dev, offset, reg); if (!rt2x00_get_field32(*reg, field)) diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.h b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.h index 9943e428bc21..bd2d59c85f1b 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -39,11 +39,17 @@ #define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops) /* + * Register defines. + * Some registers require multiple attempts before success, + * in those cases REGISTER_BUSY_COUNT attempts should be + * taken with a REGISTER_BUSY_DELAY interval. * For USB vendor requests we need to pass a timeout * time in ms, for this we use the REGISTER_TIMEOUT, * however when loading firmware a higher value is * required. In that case we use the REGISTER_TIMEOUT_FIRMWARE. */ +#define REGISTER_BUSY_COUNT 5 +#define REGISTER_BUSY_DELAY 100 #define REGISTER_TIMEOUT 500 #define REGISTER_TIMEOUT_FIRMWARE 1000 @@ -226,7 +232,7 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev, } /** - * rt2x00usb_register_read - Read 32bit register word + * rt2x00usb_regbusy_read - Read 32bit register word * @rt2x00dev: Device pointer, see &struct rt2x00_dev. * @offset: Register offset * @value: Pointer to where register contents should be stored @@ -334,13 +340,12 @@ static inline void rt2x00usb_register_write_lock(struct rt2x00_dev *rt2x00dev, * through rt2x00usb_vendor_request_buff(). */ static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - const void *value, - const u32 length) + const unsigned int offset, + void *value, const u32 length) { rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, offset, - (void *)value, length, + value, length, REGISTER_TIMEOUT32(length)); } @@ -359,7 +364,7 @@ static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, */ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, const unsigned int offset, - const struct rt2x00_field32 field, + struct rt2x00_field32 field, u32 *reg); /* diff --git a/trunk/drivers/net/wireless/rt2x00/rt73usb.c b/trunk/drivers/net/wireless/rt2x00/rt73usb.c index 14e7bb210075..b8f5ee33445e 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt73usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt73usb.c @@ -2389,13 +2389,10 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) }, /* MSI */ - { USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Ovislink */ - { USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, /* Ralink */ { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) }, @@ -2423,8 +2420,6 @@ static struct usb_device_id rt73usb_device_table[] = { /* Planex */ { USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) }, - /* WideTell */ - { USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) }, /* Zcom */ { USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) }, /* ZyXEL */ diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187.h b/trunk/drivers/net/wireless/rtl818x/rtl8187.h index abb4907cf296..bf9175a8c1f4 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8187.h +++ b/trunk/drivers/net/wireless/rtl818x/rtl8187.h @@ -119,6 +119,7 @@ struct rtl8187_priv { } hw_rev; struct sk_buff_head rx_queue; u8 signal; + u8 quality; u8 noise; u8 slot_time; u8 aifsn[4]; diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187_dev.c b/trunk/drivers/net/wireless/rtl818x/rtl8187_dev.c index 76973b8c7099..2017ccc00145 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/trunk/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -320,6 +320,7 @@ static void rtl8187_rx_cb(struct urb *urb) struct ieee80211_rx_status rx_status = { 0 }; int rate, signal; u32 flags; + u32 quality; unsigned long f; spin_lock_irqsave(&priv->rx_queue.lock, f); @@ -337,9 +338,10 @@ static void rtl8187_rx_cb(struct urb *urb) (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); flags = le32_to_cpu(hdr->flags); /* As with the RTL8187B below, the AGC is used to calculate - * signal strength. In this case, the scaling + * signal strength and quality. In this case, the scaling * constants are derived from the output of p54usb. */ + quality = 130 - ((41 * hdr->agc) >> 6); signal = -4 - ((27 * hdr->agc) >> 6); rx_status.antenna = (hdr->signal >> 7) & 1; rx_status.mactime = le64_to_cpu(hdr->mac_time); @@ -352,18 +354,23 @@ static void rtl8187_rx_cb(struct urb *urb) * In testing, none of these quantities show qualitative * agreement with AP signal strength, except for the AGC, * which is inversely proportional to the strength of the - * signal. In the following, the signal strength - * is derived from the AGC. The arbitrary scaling constants + * signal. In the following, the quality and signal strength + * are derived from the AGC. The arbitrary scaling constants * are chosen to make the results close to the values obtained * for a BCM4312 using b43 as the driver. The noise is ignored * for now. */ flags = le32_to_cpu(hdr->flags); + quality = 170 - hdr->agc; signal = 14 - hdr->agc / 2; rx_status.antenna = (hdr->rssi >> 7) & 1; rx_status.mactime = le64_to_cpu(hdr->mac_time); } + if (quality > 100) + quality = 100; + rx_status.qual = quality; + priv->quality = quality; rx_status.signal = signal; priv->signal = signal; rate = (flags >> 20) & 0xF; diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187_leds.c b/trunk/drivers/net/wireless/rtl818x/rtl8187_leds.c index cf8a4a40fdf6..a1c670fc1552 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8187_leds.c +++ b/trunk/drivers/net/wireless/rtl818x/rtl8187_leds.c @@ -210,10 +210,10 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev) /* turn the LED off before exiting */ ieee80211_queue_delayed_work(dev, &priv->led_off, 0); - rtl8187_unregister_led(&priv->led_rx); - rtl8187_unregister_led(&priv->led_tx); cancel_delayed_work_sync(&priv->led_off); cancel_delayed_work_sync(&priv->led_on); + rtl8187_unregister_led(&priv->led_rx); + rtl8187_unregister_led(&priv->led_tx); } #endif /* def CONFIG_RTL8187_LED */ diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187_rfkill.c b/trunk/drivers/net/wireless/rtl818x/rtl8187_rfkill.c index cad8037ab2af..9fab13e4004e 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8187_rfkill.c +++ b/trunk/drivers/net/wireless/rtl818x/rtl8187_rfkill.c @@ -18,7 +18,6 @@ #include #include "rtl8187.h" -#include "rtl8187_rfkill.h" static bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv) { diff --git a/trunk/drivers/staging/strip/strip.c b/trunk/drivers/net/wireless/strip.c similarity index 99% rename from trunk/drivers/staging/strip/strip.c rename to trunk/drivers/net/wireless/strip.c index 698aade79d40..ea6a87c19319 100644 --- a/trunk/drivers/staging/strip/strip.c +++ b/trunk/drivers/net/wireless/strip.c @@ -106,7 +106,6 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE"; #include #include #include -#include #include #include @@ -2726,19 +2725,6 @@ static int strip_ioctl(struct tty_struct *tty, struct file *file, return 0; } -#ifdef CONFIG_COMPAT -static long strip_compat_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case SIOCGIFNAME: - case SIOCSIFHWADDR: - return strip_ioctl(tty, file, cmd, - (unsigned long)compat_ptr(arg)); - } - return -ENOIOCTLCMD; -} -#endif /************************************************************************/ /* Initialization */ @@ -2750,9 +2736,6 @@ static struct tty_ldisc_ops strip_ldisc = { .open = strip_open, .close = strip_close, .ioctl = strip_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = strip_compat_ioctl, -#endif .receive_buf = strip_receive_buf, .write_wakeup = strip_write_some_more, }; diff --git a/trunk/drivers/staging/wavelan/wavelan.c b/trunk/drivers/net/wireless/wavelan.c similarity index 100% rename from trunk/drivers/staging/wavelan/wavelan.c rename to trunk/drivers/net/wireless/wavelan.c diff --git a/trunk/drivers/staging/wavelan/wavelan.h b/trunk/drivers/net/wireless/wavelan.h similarity index 100% rename from trunk/drivers/staging/wavelan/wavelan.h rename to trunk/drivers/net/wireless/wavelan.h diff --git a/trunk/drivers/staging/wavelan/wavelan.p.h b/trunk/drivers/net/wireless/wavelan.p.h similarity index 100% rename from trunk/drivers/staging/wavelan/wavelan.p.h rename to trunk/drivers/net/wireless/wavelan.p.h diff --git a/trunk/drivers/staging/wavelan/wavelan_cs.c b/trunk/drivers/net/wireless/wavelan_cs.c similarity index 100% rename from trunk/drivers/staging/wavelan/wavelan_cs.c rename to trunk/drivers/net/wireless/wavelan_cs.c diff --git a/trunk/drivers/staging/wavelan/wavelan_cs.h b/trunk/drivers/net/wireless/wavelan_cs.h similarity index 100% rename from trunk/drivers/staging/wavelan/wavelan_cs.h rename to trunk/drivers/net/wireless/wavelan_cs.h diff --git a/trunk/drivers/staging/wavelan/wavelan_cs.p.h b/trunk/drivers/net/wireless/wavelan_cs.p.h similarity index 100% rename from trunk/drivers/staging/wavelan/wavelan_cs.p.h rename to trunk/drivers/net/wireless/wavelan_cs.p.h diff --git a/trunk/drivers/net/wireless/wl12xx/Kconfig b/trunk/drivers/net/wireless/wl12xx/Kconfig index 785e0244e305..88060e117541 100644 --- a/trunk/drivers/net/wireless/wl12xx/Kconfig +++ b/trunk/drivers/net/wireless/wl12xx/Kconfig @@ -1,6 +1,6 @@ menuconfig WL12XX tristate "TI wl12xx driver support" - depends on MAC80211 && EXPERIMENTAL + depends on MAC80211 && WLAN_80211 && EXPERIMENTAL ---help--- This will enable TI wl12xx driver support. The drivers make use of the mac80211 stack. @@ -42,7 +42,6 @@ config WL1251_SDIO config WL1271 tristate "TI wl1271 support" depends on WL12XX && SPI_MASTER && GENERIC_HARDIRQS - depends on INET select FW_LOADER select CRC7 ---help--- diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_main.c b/trunk/drivers/net/wireless/wl12xx/wl1251_main.c index da3bf1cebc08..48b0bfd6c55a 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/trunk/drivers/net/wireless/wl12xx/wl1251_main.c @@ -1311,8 +1311,7 @@ int wl1251_init_ieee80211(struct wl1251 *wl) wl->hw->channel_change_time = 10000; wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM | - IEEE80211_HW_SUPPORTS_PS; + IEEE80211_HW_NOISE_DBM; wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); wl->hw->wiphy->max_scan_ssids = 1; diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271.h b/trunk/drivers/net/wireless/wl12xx/wl1271.h index 94359b1a861f..566f1521ec22 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1271.h +++ b/trunk/drivers/net/wireless/wl12xx/wl1271.h @@ -417,9 +417,6 @@ struct wl1271 { /* PSM mode requested */ bool psm_requested; - /* retry counter for PSM entries */ - u8 psm_entry_retry; - /* in dBm */ int power_level; diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_acx.c b/trunk/drivers/net/wireless/wl12xx/wl1271_acx.c index 5cc89bbdac7a..bf5a8680a462 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/trunk/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -141,7 +141,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power) * calibration, to avoid distortions */ /* acx->current_tx_power = power * 10; */ - acx->current_tx_power = 120; + acx->current_tx_power = 70; ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); if (ret < 0) { diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_boot.c b/trunk/drivers/net/wireless/wl12xx/wl1271_boot.c index b7c96454cca3..ba4a2b4f0f56 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/trunk/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -380,7 +380,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) } } - if (loop > INIT_LOOP) { + if (loop >= INIT_LOOP) { wl1271_error("timeout waiting for the hardware to " "complete initialization"); return -EIO; @@ -407,8 +407,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) /* unmask required mbox events */ wl->event_mask = BSS_LOSE_EVENT_ID | - SCAN_COMPLETE_EVENT_ID | - PS_REPORT_EVENT_ID; + SCAN_COMPLETE_EVENT_ID; ret = wl1271_event_unmask(wl); if (ret < 0) { diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.c b/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.c index 990eb01b4c71..0666328ce9ab 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -42,14 +42,12 @@ * @buf: buffer containing the command, must work with dma * @len: length of the buffer */ -int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, - size_t res_len) +int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len) { struct wl1271_cmd_header *cmd; unsigned long timeout; u32 intr; int ret = 0; - u16 status; cmd = buf; cmd->id = cpu_to_le16(id); @@ -76,17 +74,6 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); } - /* read back the status code of the command */ - if (res_len == 0) - res_len = sizeof(struct wl1271_cmd_header); - wl1271_spi_read(wl, wl->cmd_box_addr, cmd, res_len, false); - - status = le16_to_cpu(cmd->status); - if (status != CMD_STATUS_SUCCESS) { - wl1271_error("command execute failure %d", status); - ret = -EIO; - } - wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK, WL1271_ACX_INTR_CMD_COMPLETE); @@ -275,7 +262,7 @@ int wl1271_cmd_join(struct wl1271 *wl) wl->tx_security_seq_16 = 0; wl->tx_security_seq_32 = 0; - ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); + ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join)); if (ret < 0) { wl1271_error("failed to initiate cmd join"); goto out_free; @@ -307,21 +294,35 @@ int wl1271_cmd_join(struct wl1271 *wl) int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer) { int ret; - size_t res_len = 0; wl1271_debug(DEBUG_CMD, "cmd test"); - if (answer) - res_len = buf_len; - - ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len, res_len); + ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len); if (ret < 0) { wl1271_warning("TEST command failed"); return ret; } - return ret; + if (answer) { + struct wl1271_command *cmd_answer; + u16 status; + + /* + * The test command got in, we can read the answer. + * The answer would be a wl1271_command, where the + * parameter array contains the actual answer. + */ + wl1271_spi_read(wl, wl->cmd_box_addr, buf, buf_len, false); + + cmd_answer = buf; + status = le16_to_cpu(cmd_answer->header.status); + + if (status != CMD_STATUS_SUCCESS) + wl1271_error("TEST command answer error: %d", status); + } + + return 0; } /** @@ -344,10 +345,21 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) /* payload length, does not include any headers */ acx->len = cpu_to_le16(len - sizeof(*acx)); - ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx), len); - if (ret < 0) + ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx)); + if (ret < 0) { wl1271_error("INTERROGATE command failed"); + goto out; + } + /* the interrogate command got in, we can read the answer */ + wl1271_spi_read(wl, wl->cmd_box_addr, buf, len, false); + + acx = buf; + if (le16_to_cpu(acx->cmd.status) != CMD_STATUS_SUCCESS) + wl1271_error("INTERROGATE command error: %d", + le16_to_cpu(acx->cmd.status)); + +out: return ret; } @@ -371,7 +383,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) /* payload length, does not include any headers */ acx->len = cpu_to_le16(len - sizeof(*acx)); - ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len, 0); + ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len); if (ret < 0) { wl1271_warning("CONFIGURE command NOK"); return ret; @@ -404,7 +416,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) cmd_tx = CMD_DISABLE_TX; } - ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd)); if (ret < 0) { wl1271_error("rx %s cmd for channel %d failed", enable ? "start" : "stop", channel); @@ -414,7 +426,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", enable ? "start" : "stop", channel); - ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd)); if (ret < 0) { wl1271_error("tx %s cmd for channel %d failed", enable ? "start" : "stop", channel); @@ -456,7 +468,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, - sizeof(*ps_params), 0); + sizeof(*ps_params)); if (ret < 0) { wl1271_error("cmd set_ps_mode failed"); goto out; @@ -487,14 +499,19 @@ int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, cmd->addr = cpu_to_le32(addr); cmd->size = cpu_to_le32(len); - ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd), - sizeof(*cmd)); + ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd)); if (ret < 0) { wl1271_error("read memory command failed: %d", ret); goto out; } - /* the read command got in */ + /* the read command got in, we can now read the answer */ + wl1271_spi_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd), false); + + if (le16_to_cpu(cmd->header.status) != CMD_STATUS_SUCCESS) + wl1271_error("error in read command result: %d", + le16_to_cpu(cmd->header.status)); + memcpy(answer, cmd->value, len); out: @@ -596,7 +613,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, trigger->timeout = 0; ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, - sizeof(*trigger), 0); + sizeof(*trigger)); if (ret < 0) { wl1271_error("trigger scan to failed for hw scan"); goto out; @@ -619,10 +636,20 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, } } - ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); + ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params)); if (ret < 0) { wl1271_error("SCAN failed"); + goto out; + } + + wl1271_spi_read(wl, wl->cmd_box_addr, params, sizeof(*params), + false); + + if (le16_to_cpu(params->header.status) != CMD_STATUS_SUCCESS) { + wl1271_error("Scan command error: %d", + le16_to_cpu(params->header.status)); wl->scanning = false; + ret = -EIO; goto out; } @@ -657,7 +684,7 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, if (buf) memcpy(cmd->template_data, buf, buf_len); - ret = wl1271_cmd_send(wl, CMD_SET_TEMPLATE, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, CMD_SET_TEMPLATE, cmd, sizeof(*cmd)); if (ret < 0) { wl1271_warning("cmd set_template failed: %d", ret); goto out_free; @@ -836,7 +863,7 @@ int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) cmd->key_action = cpu_to_le16(KEY_SET_ID); cmd->key_type = KEY_WEP; - ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd)); if (ret < 0) { wl1271_warning("cmd set_default_wep_key failed: %d", ret); goto out; @@ -893,7 +920,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, wl1271_dump(DEBUG_CRYPT, "TARGET KEY: ", cmd, sizeof(*cmd)); - ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd)); if (ret < 0) { wl1271_warning("could not set keys"); goto out; @@ -923,7 +950,7 @@ int wl1271_cmd_disconnect(struct wl1271 *wl) /* disconnect reason is not used in immediate disconnections */ cmd->type = DISCONNECT_IMMEDIATE; - ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd)); if (ret < 0) { wl1271_error("failed to send disconnect command"); goto out_free; diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.h b/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.h index 9d7061b3c8a0..174b8209dbf3 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/trunk/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -29,8 +29,7 @@ struct acx_header; -int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, - size_t res_len); +int wl1271_cmd_send(struct wl1271 *wl, u16 type, void *buf, size_t buf_len); int wl1271_cmd_join(struct wl1271 *wl); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_conf.h b/trunk/drivers/net/wireless/wl12xx/wl1271_conf.h index 565373ede265..061d47520a32 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/trunk/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -712,14 +712,6 @@ struct conf_conn_settings { * Range 0 - 255 */ u8 bet_max_consecutive; - - /* - * Specifies the maximum number of times to try PSM entry if it fails - * (if sending the appropriate null-func message fails.) - * - * Range 0 - 255 - */ - u8 psm_entry_retries; }; #define CONF_SR_ERR_TBL_MAX_VALUES 14 diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_event.c b/trunk/drivers/net/wireless/wl12xx/wl1271_event.c index e135d894b42a..31d396ba9188 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/trunk/drivers/net/wireless/wl12xx/wl1271_event.c @@ -68,40 +68,6 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, return 0; } -static int wl1271_event_ps_report(struct wl1271 *wl, - struct event_mailbox *mbox, - bool *beacon_loss) -{ - int ret = 0; - - wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status); - - switch (mbox->ps_status) { - case EVENT_ENTER_POWER_SAVE_FAIL: - if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) { - wl->psm_entry_retry++; - wl1271_error("PSM entry failed, retrying %d\n", - wl->psm_entry_retry); - ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); - } else { - wl->psm_entry_retry = 0; - *beacon_loss = true; - } - break; - case EVENT_ENTER_POWER_SAVE_SUCCESS: - wl->psm_entry_retry = 0; - break; - case EVENT_EXIT_POWER_SAVE_FAIL: - wl1271_info("PSM exit failed"); - break; - case EVENT_EXIT_POWER_SAVE_SUCCESS: - default: - break; - } - - return ret; -} - static void wl1271_event_mbox_dump(struct event_mailbox *mbox) { wl1271_debug(DEBUG_EVENT, "MBOX DUMP:"); @@ -113,7 +79,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) { int ret; u32 vector; - bool beacon_loss = false; wl1271_event_mbox_dump(mbox); @@ -136,25 +101,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); /* indicate to the stack, that beacons have been lost */ - beacon_loss = true; - } - - if (vector & PS_REPORT_EVENT_ID) { - wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); - ret = wl1271_event_ps_report(wl, mbox, &beacon_loss); - if (ret < 0) - return ret; - } - - if (beacon_loss) { - /* Obviously, it's dangerous to release the mutex while - we are holding many of the variables in the wl struct. - That's why it's done last in the function, and care must - be taken that nothing more is done after this function - returns. */ - mutex_unlock(&wl->mutex); ieee80211_beacon_loss(wl->vif); - mutex_lock(&wl->mutex); } return 0; diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_event.h b/trunk/drivers/net/wireless/wl12xx/wl1271_event.h index 4e3f55ebb1a8..3ab53d331f15 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/trunk/drivers/net/wireless/wl12xx/wl1271_event.h @@ -63,13 +63,6 @@ enum { EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff, }; -enum { - EVENT_ENTER_POWER_SAVE_FAIL = 0, - EVENT_ENTER_POWER_SAVE_SUCCESS, - EVENT_EXIT_POWER_SAVE_FAIL, - EVENT_EXIT_POWER_SAVE_SUCCESS, -}; - struct event_debug_report { u8 debug_event_id; u8 num_params; diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_init.c b/trunk/drivers/net/wireless/wl12xx/wl1271_init.c index 7c2017f480ea..417b4152feb1 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/trunk/drivers/net/wireless/wl12xx/wl1271_init.c @@ -303,15 +303,12 @@ int wl1271_hw_init(struct wl1271 *wl) { int ret; - /* FIXME: the following parameter setting functions return error - * codes - the reason is so far unknown. The -EIO is therefore - * ignored for the time being. */ ret = wl1271_init_general_parms(wl); - if (ret < 0 && ret != -EIO) + if (ret < 0) return ret; ret = wl1271_init_radio_parms(wl); - if (ret < 0 && ret != -EIO) + if (ret < 0) return ret; /* Template settings */ diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_main.c b/trunk/drivers/net/wireless/wl12xx/wl1271_main.c index d2149fcd3cf1..86132bb00787 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/trunk/drivers/net/wireless/wl12xx/wl1271_main.c @@ -222,8 +222,7 @@ static struct conf_drv_settings default_conf = { .snr_pkt_avg_weight = 10 }, .bet_enable = CONF_BET_MODE_ENABLE, - .bet_max_consecutive = 100, - .psm_entry_retries = 3 + .bet_max_consecutive = 100 }, .init = { .sr_err_tbl = { @@ -974,7 +973,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->rx_counter = 0; wl->elp = false; wl->psm = 0; - wl->psm_entry_retry = 0; wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->tx_blocks_available = 0; @@ -1069,12 +1067,12 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw, ret = wl1271_cmd_join(wl); if (ret < 0) goto out_sleep; - - ret = wl1271_cmd_build_null_data(wl); - if (ret < 0) - goto out_sleep; } + ret = wl1271_cmd_build_null_data(wl); + if (ret < 0) + goto out_sleep; + wl->ssid_len = conf->ssid_len; if (wl->ssid_len) memcpy(wl->ssid, conf->ssid, wl->ssid_len); @@ -1139,6 +1137,10 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl->channel = channel; } + ret = wl1271_cmd_build_null_data(wl); + if (ret < 0) + goto out_sleep; + if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { wl1271_info("psm enabled"); @@ -1163,7 +1165,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (conf->power_level != wl->power_level) { ret = wl1271_acx_tx_power(wl, conf->power_level); if (ret < 0) - goto out_sleep; + goto out; wl->power_level = conf->power_level; } @@ -1824,7 +1826,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) wl->elp = false; wl->psm = 0; wl->psm_requested = false; - wl->psm_entry_retry = 0; wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_rx.c b/trunk/drivers/net/wireless/wl12xx/wl1271_rx.c index ca645f38109b..37d81ab6acc0 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/trunk/drivers/net/wireless/wl12xx/wl1271_rx.c @@ -159,7 +159,7 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) u8 *buf; u8 beacon = 0; - skb = __dev_alloc_skb(length, GFP_KERNEL); + skb = dev_alloc_skb(length); if (!skb) { wl1271_error("Couldn't allocate RX frame"); return; diff --git a/trunk/drivers/net/wireless/zd1211rw/Kconfig b/trunk/drivers/net/wireless/zd1211rw/Kconfig index 5f809695f71a..74b31eafe72d 100644 --- a/trunk/drivers/net/wireless/zd1211rw/Kconfig +++ b/trunk/drivers/net/wireless/zd1211rw/Kconfig @@ -1,6 +1,6 @@ config ZD1211RW tristate "ZyDAS ZD1211/ZD1211B USB-wireless support" - depends on USB && MAC80211 && EXPERIMENTAL + depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL select FW_LOADER ---help--- This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless diff --git a/trunk/drivers/parisc/led.c b/trunk/drivers/parisc/led.c index 79caf1ca4a29..9581d3619450 100644 --- a/trunk/drivers/parisc/led.c +++ b/trunk/drivers/parisc/led.c @@ -352,9 +352,11 @@ static __inline__ int led_get_net_activity(void) rx_total = tx_total = 0; - /* we are running as a workqueue task, so we can use an RCU lookup */ + /* we are running as a workqueue task, so locking dev_base + * for reading should be OK */ + read_lock(&dev_base_lock); rcu_read_lock(); - for_each_netdev_rcu(&init_net, dev) { + for_each_netdev(&init_net, dev) { const struct net_device_stats *stats; struct in_device *in_dev = __in_dev_get_rcu(dev); if (!in_dev || !in_dev->ifa_list) @@ -366,6 +368,7 @@ static __inline__ int led_get_net_activity(void) tx_total += stats->tx_packets; } rcu_read_unlock(); + read_unlock(&dev_base_lock); retval = 0; diff --git a/trunk/drivers/s390/net/Makefile b/trunk/drivers/s390/net/Makefile index 6cab5a62f99e..96eddb3b1d08 100644 --- a/trunk/drivers/s390/net/Makefile +++ b/trunk/drivers/s390/net/Makefile @@ -3,11 +3,11 @@ # ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o -obj-$(CONFIG_CTCM) += ctcm.o fsm.o +obj-$(CONFIG_CTCM) += ctcm.o fsm.o cu3088.o obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o obj-$(CONFIG_SMSGIUCV) += smsgiucv.o -obj-$(CONFIG_LCS) += lcs.o -obj-$(CONFIG_CLAW) += claw.o +obj-$(CONFIG_LCS) += lcs.o cu3088.o +obj-$(CONFIG_CLAW) += claw.o cu3088.o qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o obj-$(CONFIG_QETH) += qeth.o qeth_l2-y += qeth_l2_main.o diff --git a/trunk/drivers/s390/net/claw.c b/trunk/drivers/s390/net/claw.c index cf283e3d2763..c63babefb698 100644 --- a/trunk/drivers/s390/net/claw.c +++ b/trunk/drivers/s390/net/claw.c @@ -90,6 +90,7 @@ #include #include +#include "cu3088.h" #include "claw.h" /* @@ -257,9 +258,6 @@ static int claw_pm_prepare(struct ccwgroup_device *gdev) return -EPERM; } -/* the root device for claw group devices */ -static struct device *claw_root_dev; - /* ccwgroup table */ static struct ccwgroup_driver claw_group_driver = { @@ -274,47 +272,6 @@ static struct ccwgroup_driver claw_group_driver = { .prepare = claw_pm_prepare, }; -static struct ccw_device_id claw_ids[] = { - {CCW_DEVICE(0x3088, 0x61), .driver_info = claw_channel_type_claw}, - {}, -}; -MODULE_DEVICE_TABLE(ccw, claw_ids); - -static struct ccw_driver claw_ccw_driver = { - .owner = THIS_MODULE, - .name = "claw", - .ids = claw_ids, - .probe = ccwgroup_probe_ccwdev, - .remove = ccwgroup_remove_ccwdev, -}; - -static ssize_t -claw_driver_group_store(struct device_driver *ddrv, const char *buf, - size_t count) -{ - int err; - err = ccwgroup_create_from_string(claw_root_dev, - claw_group_driver.driver_id, - &claw_ccw_driver, 3, buf); - return err ? err : count; -} - -static DRIVER_ATTR(group, 0200, NULL, claw_driver_group_store); - -static struct attribute *claw_group_attrs[] = { - &driver_attr_group.attr, - NULL, -}; - -static struct attribute_group claw_group_attr_group = { - .attrs = claw_group_attrs, -}; - -static struct attribute_group *claw_group_attr_groups[] = { - &claw_group_attr_group, - NULL, -}; - /* * Key functions */ @@ -3369,11 +3326,7 @@ claw_remove_files(struct device *dev) static void __exit claw_cleanup(void) { - driver_remove_file(&claw_group_driver.driver, - &driver_attr_group); - ccwgroup_driver_unregister(&claw_group_driver); - ccw_driver_unregister(&claw_ccw_driver); - root_device_unregister(claw_root_dev); + unregister_cu3088_discipline(&claw_group_driver); claw_unregister_debug_facility(); pr_info("Driver unloaded\n"); @@ -3395,31 +3348,16 @@ claw_init(void) if (ret) { pr_err("Registering with the S/390 debug feature" " failed with error code %d\n", ret); - goto out_err; + return ret; } CLAW_DBF_TEXT(2, setup, "init_mod"); - claw_root_dev = root_device_register("qeth"); - ret = IS_ERR(claw_root_dev) ? PTR_ERR(claw_root_dev) : 0; - if (ret) - goto register_err; - ret = ccw_driver_register(&claw_ccw_driver); - if (ret) - goto ccw_err; - claw_group_driver.driver.groups = claw_group_attr_groups; - ret = ccwgroup_driver_register(&claw_group_driver); - if (ret) - goto ccwgroup_err; - return 0; - -ccwgroup_err: - ccw_driver_unregister(&claw_ccw_driver); -ccw_err: - root_device_unregister(claw_root_dev); -register_err: - CLAW_DBF_TEXT(2, setup, "init_bad"); - claw_unregister_debug_facility(); -out_err: - pr_err("Initializing the claw device driver failed\n"); + ret = register_cu3088_discipline(&claw_group_driver); + if (ret) { + CLAW_DBF_TEXT(2, setup, "init_bad"); + claw_unregister_debug_facility(); + pr_err("Registering with the cu3088 device driver failed " + "with error code %d\n", ret); + } return ret; } diff --git a/trunk/drivers/s390/net/claw.h b/trunk/drivers/s390/net/claw.h index 46d59a13db12..005072c420d3 100644 --- a/trunk/drivers/s390/net/claw.h +++ b/trunk/drivers/s390/net/claw.h @@ -129,18 +129,6 @@ static inline int claw_dbf_passes(debug_info_t *dbf_grp, int level) } \ } while (0) -/** - * Enum for classifying detected devices. - */ -enum claw_channel_types { - /* Device is not a channel */ - claw_channel_type_none, - - /* Device is a CLAW channel device */ - claw_channel_type_claw -}; - - /******************************************************* * Define Control Blocks * * * diff --git a/trunk/drivers/s390/net/ctcm_fsms.c b/trunk/drivers/s390/net/ctcm_fsms.c index 70eb7f138414..4ded9ac2c5ef 100644 --- a/trunk/drivers/s390/net/ctcm_fsms.c +++ b/trunk/drivers/s390/net/ctcm_fsms.c @@ -44,6 +44,7 @@ #include #include "fsm.h" +#include "cu3088.h" #include "ctcm_dbug.h" #include "ctcm_main.h" diff --git a/trunk/drivers/s390/net/ctcm_fsms.h b/trunk/drivers/s390/net/ctcm_fsms.h index 046d077fabbb..2326aba9807a 100644 --- a/trunk/drivers/s390/net/ctcm_fsms.h +++ b/trunk/drivers/s390/net/ctcm_fsms.h @@ -39,6 +39,7 @@ #include #include "fsm.h" +#include "cu3088.h" #include "ctcm_main.h" /* diff --git a/trunk/drivers/s390/net/ctcm_main.c b/trunk/drivers/s390/net/ctcm_main.c index 558dc323a947..db054ed1a8cc 100644 --- a/trunk/drivers/s390/net/ctcm_main.c +++ b/trunk/drivers/s390/net/ctcm_main.c @@ -51,16 +51,12 @@ #include +#include "cu3088.h" #include "ctcm_fsms.h" #include "ctcm_main.h" /* Some common global variables */ -/** - * The root device for ctcm group devices - */ -static struct device *ctcm_root_dev; - /* * Linked list of all detected channels. */ @@ -250,7 +246,7 @@ static void channel_remove(struct channel *ch) * * returns Pointer to a channel or NULL if no matching channel available. */ -static struct channel *channel_get(enum ctcm_channel_types type, +static struct channel *channel_get(enum channel_types type, char *id, int direction) { struct channel *ch = channels; @@ -1346,7 +1342,7 @@ static int ctcm_probe_device(struct ccwgroup_device *cgdev) * * returns 0 on success, !0 on error. */ -static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type, +static int add_channel(struct ccw_device *cdev, enum channel_types type, struct ctcm_priv *priv) { struct channel **c = &channels; @@ -1505,13 +1501,13 @@ static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type, /* * Return type of a detected device. */ -static enum ctcm_channel_types get_channel_type(struct ccw_device_id *id) +static enum channel_types get_channel_type(struct ccw_device_id *id) { - enum ctcm_channel_types type; - type = (enum ctcm_channel_types)id->driver_info; + enum channel_types type; + type = (enum channel_types)id->driver_info; - if (type == ctcm_channel_type_ficon) - type = ctcm_channel_type_escon; + if (type == channel_type_ficon) + type = channel_type_escon; return type; } @@ -1529,7 +1525,7 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) char read_id[CTCM_ID_SIZE]; char write_id[CTCM_ID_SIZE]; int direction; - enum ctcm_channel_types type; + enum channel_types type; struct ctcm_priv *priv; struct net_device *dev; struct ccw_device *cdev0; @@ -1724,11 +1720,6 @@ static int ctcm_pm_suspend(struct ccwgroup_device *gdev) return 0; netif_device_detach(priv->channel[READ]->netdev); ctcm_close(priv->channel[READ]->netdev); - if (!wait_event_timeout(priv->fsm->wait_q, - fsm_getstate(priv->fsm) == DEV_STATE_STOPPED, CTCM_TIME_5_SEC)) { - netif_device_attach(priv->channel[READ]->netdev); - return -EBUSY; - } ccw_device_set_offline(gdev->cdev[1]); ccw_device_set_offline(gdev->cdev[0]); return 0; @@ -1753,22 +1744,6 @@ static int ctcm_pm_resume(struct ccwgroup_device *gdev) return rc; } -static struct ccw_device_id ctcm_ids[] = { - {CCW_DEVICE(0x3088, 0x08), .driver_info = ctcm_channel_type_parallel}, - {CCW_DEVICE(0x3088, 0x1e), .driver_info = ctcm_channel_type_ficon}, - {CCW_DEVICE(0x3088, 0x1f), .driver_info = ctcm_channel_type_escon}, - {}, -}; -MODULE_DEVICE_TABLE(ccw, ctcm_ids); - -static struct ccw_driver ctcm_ccw_driver = { - .owner = THIS_MODULE, - .name = "ctcm", - .ids = ctcm_ids, - .probe = ccwgroup_probe_ccwdev, - .remove = ccwgroup_remove_ccwdev, -}; - static struct ccwgroup_driver ctcm_group_driver = { .owner = THIS_MODULE, .name = CTC_DRIVER_NAME, @@ -1783,33 +1758,6 @@ static struct ccwgroup_driver ctcm_group_driver = { .restore = ctcm_pm_resume, }; -static ssize_t -ctcm_driver_group_store(struct device_driver *ddrv, const char *buf, - size_t count) -{ - int err; - - err = ccwgroup_create_from_string(ctcm_root_dev, - ctcm_group_driver.driver_id, - &ctcm_ccw_driver, 2, buf); - return err ? err : count; -} - -static DRIVER_ATTR(group, 0200, NULL, ctcm_driver_group_store); - -static struct attribute *ctcm_group_attrs[] = { - &driver_attr_group.attr, - NULL, -}; - -static struct attribute_group ctcm_group_attr_group = { - .attrs = ctcm_group_attrs, -}; - -static struct attribute_group *ctcm_group_attr_groups[] = { - &ctcm_group_attr_group, - NULL, -}; /* * Module related routines @@ -1823,10 +1771,7 @@ static struct attribute_group *ctcm_group_attr_groups[] = { */ static void __exit ctcm_exit(void) { - driver_remove_file(&ctcm_group_driver.driver, &driver_attr_group); - ccwgroup_driver_unregister(&ctcm_group_driver); - ccw_driver_unregister(&ctcm_ccw_driver); - root_device_unregister(ctcm_root_dev); + unregister_cu3088_discipline(&ctcm_group_driver); ctcm_unregister_dbf_views(); pr_info("CTCM driver unloaded\n"); } @@ -1852,31 +1797,17 @@ static int __init ctcm_init(void) channels = NULL; ret = ctcm_register_dbf_views(); - if (ret) - goto out_err; - ctcm_root_dev = root_device_register("ctcm"); - ret = IS_ERR(ctcm_root_dev) ? PTR_ERR(ctcm_root_dev) : 0; - if (ret) - goto register_err; - ret = ccw_driver_register(&ctcm_ccw_driver); - if (ret) - goto ccw_err; - ctcm_group_driver.driver.groups = ctcm_group_attr_groups; - ret = ccwgroup_driver_register(&ctcm_group_driver); - if (ret) - goto ccwgroup_err; + if (ret) { + return ret; + } + ret = register_cu3088_discipline(&ctcm_group_driver); + if (ret) { + ctcm_unregister_dbf_views(); + pr_err("%s / register_cu3088_discipline failed, ret = %d\n", + __func__, ret); + return ret; + } print_banner(); - return 0; - -ccwgroup_err: - ccw_driver_unregister(&ctcm_ccw_driver); -ccw_err: - root_device_unregister(ctcm_root_dev); -register_err: - ctcm_unregister_dbf_views(); -out_err: - pr_err("%s / Initializing the ctcm device driver failed, ret = %d\n", - __func__, ret); return ret; } diff --git a/trunk/drivers/s390/net/ctcm_main.h b/trunk/drivers/s390/net/ctcm_main.h index d34fa14f44e7..d925e732b7d8 100644 --- a/trunk/drivers/s390/net/ctcm_main.h +++ b/trunk/drivers/s390/net/ctcm_main.h @@ -16,6 +16,7 @@ #include #include "fsm.h" +#include "cu3088.h" #include "ctcm_dbug.h" #include "ctcm_mpc.h" @@ -65,23 +66,6 @@ ctcmpc_dumpit(buf, len); \ } while (0) -/** - * Enum for classifying detected devices - */ -enum ctcm_channel_types { - /* Device is not a channel */ - ctcm_channel_type_none, - - /* Device is a CTC/A */ - ctcm_channel_type_parallel, - - /* Device is a FICON channel */ - ctcm_channel_type_ficon, - - /* Device is a ESCON channel */ - ctcm_channel_type_escon -}; - /* * CCW commands, used in this driver. */ @@ -137,7 +121,7 @@ struct channel { * Type of this channel. * CTC/A or Escon for valid channels. */ - enum ctcm_channel_types type; + enum channel_types type; /* * Misc. flags. See CHANNEL_FLAGS_... below */ diff --git a/trunk/drivers/s390/net/ctcm_mpc.c b/trunk/drivers/s390/net/ctcm_mpc.c index 5978b390153f..781e18be7e8f 100644 --- a/trunk/drivers/s390/net/ctcm_mpc.c +++ b/trunk/drivers/s390/net/ctcm_mpc.c @@ -53,6 +53,7 @@ #include #include +#include "cu3088.h" #include "ctcm_mpc.h" #include "ctcm_main.h" #include "ctcm_fsms.h" diff --git a/trunk/drivers/s390/net/ctcm_sysfs.c b/trunk/drivers/s390/net/ctcm_sysfs.c index 738ad26c74a7..8452bb052d68 100644 --- a/trunk/drivers/s390/net/ctcm_sysfs.c +++ b/trunk/drivers/s390/net/ctcm_sysfs.c @@ -158,15 +158,6 @@ static ssize_t ctcm_proto_store(struct device *dev, return count; } -const char *ctcm_type[] = { - "not a channel", - "CTC/A", - "FICON channel", - "ESCON channel", - "unknown channel type", - "unsupported channel type", -}; - static ssize_t ctcm_type_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -177,7 +168,7 @@ static ssize_t ctcm_type_show(struct device *dev, return -ENODEV; return sprintf(buf, "%s\n", - ctcm_type[cgdev->cdev[0]->id.driver_info]); + cu3088_type[cgdev->cdev[0]->id.driver_info]); } static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write); diff --git a/trunk/drivers/s390/net/cu3088.c b/trunk/drivers/s390/net/cu3088.c new file mode 100644 index 000000000000..48383459e99b --- /dev/null +++ b/trunk/drivers/s390/net/cu3088.c @@ -0,0 +1,148 @@ +/* + * CTC / LCS ccw_device driver + * + * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Arnd Bergmann + * Cornelia Huck + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include + +#include +#include + +#include "cu3088.h" + +const char *cu3088_type[] = { + "not a channel", + "CTC/A", + "ESCON channel", + "FICON channel", + "OSA LCS card", + "CLAW channel device", + "unknown channel type", + "unsupported channel type", +}; + +/* static definitions */ + +static struct ccw_device_id cu3088_ids[] = { + { CCW_DEVICE(0x3088, 0x08), .driver_info = channel_type_parallel }, + { CCW_DEVICE(0x3088, 0x1f), .driver_info = channel_type_escon }, + { CCW_DEVICE(0x3088, 0x1e), .driver_info = channel_type_ficon }, + { CCW_DEVICE(0x3088, 0x60), .driver_info = channel_type_osa2 }, + { CCW_DEVICE(0x3088, 0x61), .driver_info = channel_type_claw }, + { /* end of list */ } +}; + +static struct ccw_driver cu3088_driver; + +static struct device *cu3088_root_dev; + +static ssize_t +group_write(struct device_driver *drv, const char *buf, size_t count) +{ + int ret; + struct ccwgroup_driver *cdrv; + + cdrv = to_ccwgroupdrv(drv); + if (!cdrv) + return -EINVAL; + ret = ccwgroup_create_from_string(cu3088_root_dev, cdrv->driver_id, + &cu3088_driver, 2, buf); + + return (ret == 0) ? count : ret; +} + +static DRIVER_ATTR(group, 0200, NULL, group_write); + +/* Register-unregister for ctc&lcs */ +int +register_cu3088_discipline(struct ccwgroup_driver *dcp) +{ + int rc; + + if (!dcp) + return -EINVAL; + + /* Register discipline.*/ + rc = ccwgroup_driver_register(dcp); + if (rc) + return rc; + + rc = driver_create_file(&dcp->driver, &driver_attr_group); + if (rc) + ccwgroup_driver_unregister(dcp); + + return rc; + +} + +void +unregister_cu3088_discipline(struct ccwgroup_driver *dcp) +{ + if (!dcp) + return; + + driver_remove_file(&dcp->driver, &driver_attr_group); + ccwgroup_driver_unregister(dcp); +} + +static struct ccw_driver cu3088_driver = { + .owner = THIS_MODULE, + .ids = cu3088_ids, + .name = "cu3088", + .probe = ccwgroup_probe_ccwdev, + .remove = ccwgroup_remove_ccwdev, +}; + +/* module setup */ +static int __init +cu3088_init (void) +{ + int rc; + + cu3088_root_dev = root_device_register("cu3088"); + if (IS_ERR(cu3088_root_dev)) + return PTR_ERR(cu3088_root_dev); + rc = ccw_driver_register(&cu3088_driver); + if (rc) + root_device_unregister(cu3088_root_dev); + + return rc; +} + +static void __exit +cu3088_exit (void) +{ + ccw_driver_unregister(&cu3088_driver); + root_device_unregister(cu3088_root_dev); +} + +MODULE_DEVICE_TABLE(ccw,cu3088_ids); +MODULE_AUTHOR("Arnd Bergmann "); +MODULE_LICENSE("GPL"); + +module_init(cu3088_init); +module_exit(cu3088_exit); + +EXPORT_SYMBOL_GPL(cu3088_type); +EXPORT_SYMBOL_GPL(register_cu3088_discipline); +EXPORT_SYMBOL_GPL(unregister_cu3088_discipline); diff --git a/trunk/drivers/s390/net/cu3088.h b/trunk/drivers/s390/net/cu3088.h new file mode 100644 index 000000000000..d8558a7105a5 --- /dev/null +++ b/trunk/drivers/s390/net/cu3088.h @@ -0,0 +1,41 @@ +#ifndef _CU3088_H +#define _CU3088_H + +/** + * Enum for classifying detected devices. + */ +enum channel_types { + /* Device is not a channel */ + channel_type_none, + + /* Device is a CTC/A */ + channel_type_parallel, + + /* Device is a ESCON channel */ + channel_type_escon, + + /* Device is a FICON channel */ + channel_type_ficon, + + /* Device is a OSA2 card */ + channel_type_osa2, + + /* Device is a CLAW channel device */ + channel_type_claw, + + /* Device is a channel, but we don't know + * anything about it */ + channel_type_unknown, + + /* Device is an unsupported model */ + channel_type_unsupported, + + /* number of type entries */ + num_channel_types +}; + +extern const char *cu3088_type[num_channel_types]; +extern int register_cu3088_discipline(struct ccwgroup_driver *); +extern void unregister_cu3088_discipline(struct ccwgroup_driver *); + +#endif diff --git a/trunk/drivers/s390/net/fsm.c b/trunk/drivers/s390/net/fsm.c index cae48cbc5e96..2c1db8036b7c 100644 --- a/trunk/drivers/s390/net/fsm.c +++ b/trunk/drivers/s390/net/fsm.c @@ -27,7 +27,6 @@ init_fsm(char *name, const char **state_names, const char **event_names, int nr_ return NULL; } strlcpy(this->name, name, sizeof(this->name)); - init_waitqueue_head(&this->wait_q); f = kzalloc(sizeof(fsm), order); if (f == NULL) { diff --git a/trunk/drivers/s390/net/fsm.h b/trunk/drivers/s390/net/fsm.h index 1e8b235d95b5..af679c10f1bd 100644 --- a/trunk/drivers/s390/net/fsm.h +++ b/trunk/drivers/s390/net/fsm.h @@ -66,7 +66,6 @@ typedef struct fsm_instance_t { char name[16]; void *userdata; int userint; - wait_queue_head_t wait_q; #if FSM_DEBUG_HISTORY int history_index; int history_size; @@ -198,7 +197,6 @@ fsm_newstate(fsm_instance *fi, int newstate) printk(KERN_DEBUG "fsm(%s): New state %s\n", fi->name, fi->f->state_names[newstate]); #endif - wake_up(&fi->wait_q); } /** diff --git a/trunk/drivers/s390/net/lcs.c b/trunk/drivers/s390/net/lcs.c index 1d43d23f5ea3..5e46415d3e13 100644 --- a/trunk/drivers/s390/net/lcs.c +++ b/trunk/drivers/s390/net/lcs.c @@ -47,6 +47,7 @@ #include #include "lcs.h" +#include "cu3088.h" #if !defined(CONFIG_NET_ETHERNET) && \ @@ -59,11 +60,7 @@ */ static char version[] __initdata = "LCS driver"; - -/** - * the root device for lcs group devices - */ -static struct device *lcs_root_dev; +static char debug_buffer[255]; /** * Some prototypes. @@ -79,7 +76,6 @@ static int lcs_recovery(void *ptr); /** * Debug Facility Stuff */ -static char debug_buffer[255]; static debug_info_t *lcs_dbf_setup; static debug_info_t *lcs_dbf_trace; @@ -1972,15 +1968,6 @@ lcs_portno_store (struct device *dev, struct device_attribute *attr, const char static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store); -const char *lcs_type[] = { - "not a channel", - "2216 parallel", - "2216 channel", - "OSA LCS card", - "unknown channel type", - "unsupported channel type", -}; - static ssize_t lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1990,7 +1977,7 @@ lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf) if (!cgdev) return -ENODEV; - return sprintf(buf, "%s\n", lcs_type[cgdev->cdev[0]->id.driver_info]); + return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]); } static DEVICE_ATTR(type, 0444, lcs_type_show, NULL); @@ -2383,22 +2370,6 @@ static int lcs_restore(struct ccwgroup_device *gdev) return lcs_pm_resume(card); } -static struct ccw_device_id lcs_ids[] = { - {CCW_DEVICE(0x3088, 0x08), .driver_info = lcs_channel_type_parallel}, - {CCW_DEVICE(0x3088, 0x1f), .driver_info = lcs_channel_type_2216}, - {CCW_DEVICE(0x3088, 0x60), .driver_info = lcs_channel_type_osa2}, - {}, -}; -MODULE_DEVICE_TABLE(ccw, lcs_ids); - -static struct ccw_driver lcs_ccw_driver = { - .owner = THIS_MODULE, - .name = "lcs", - .ids = lcs_ids, - .probe = ccwgroup_probe_ccwdev, - .remove = ccwgroup_remove_ccwdev, -}; - /** * LCS ccwgroup driver registration */ @@ -2418,33 +2389,6 @@ static struct ccwgroup_driver lcs_group_driver = { .restore = lcs_restore, }; -static ssize_t -lcs_driver_group_store(struct device_driver *ddrv, const char *buf, - size_t count) -{ - int err; - err = ccwgroup_create_from_string(lcs_root_dev, - lcs_group_driver.driver_id, - &lcs_ccw_driver, 2, buf); - return err ? err : count; -} - -static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store); - -static struct attribute *lcs_group_attrs[] = { - &driver_attr_group.attr, - NULL, -}; - -static struct attribute_group lcs_group_attr_group = { - .attrs = lcs_group_attrs, -}; - -static struct attribute_group *lcs_group_attr_groups[] = { - &lcs_group_attr_group, - NULL, -}; - /** * LCS Module/Kernel initialization function */ @@ -2456,30 +2400,17 @@ __init lcs_init_module(void) pr_info("Loading %s\n", version); rc = lcs_register_debug_facility(); LCS_DBF_TEXT(0, setup, "lcsinit"); - if (rc) - goto out_err; - lcs_root_dev = root_device_register("lcs"); - rc = IS_ERR(lcs_root_dev) ? PTR_ERR(lcs_root_dev) : 0; - if (rc) - goto register_err; - rc = ccw_driver_register(&lcs_ccw_driver); - if (rc) - goto ccw_err; - lcs_group_driver.driver.groups = lcs_group_attr_groups; - rc = ccwgroup_driver_register(&lcs_group_driver); - if (rc) - goto ccwgroup_err; - return 0; + if (rc) { + pr_err("Initialization failed\n"); + return rc; + } -ccwgroup_err: - ccw_driver_unregister(&lcs_ccw_driver); -ccw_err: - root_device_unregister(lcs_root_dev); -register_err: - lcs_unregister_debug_facility(); -out_err: - pr_err("Initializing the lcs device driver failed\n"); - return rc; + rc = register_cu3088_discipline(&lcs_group_driver); + if (rc) { + pr_err("Initialization failed\n"); + return rc; + } + return 0; } @@ -2491,11 +2422,7 @@ __exit lcs_cleanup_module(void) { pr_info("Terminating lcs module.\n"); LCS_DBF_TEXT(0, trace, "cleanup"); - driver_remove_file(&lcs_group_driver.driver, - &driver_attr_group); - ccwgroup_driver_unregister(&lcs_group_driver); - ccw_driver_unregister(&lcs_ccw_driver); - root_device_unregister(lcs_root_dev); + unregister_cu3088_discipline(&lcs_group_driver); lcs_unregister_debug_facility(); } diff --git a/trunk/drivers/s390/net/lcs.h b/trunk/drivers/s390/net/lcs.h index 8c03392ac833..6d668642af27 100644 --- a/trunk/drivers/s390/net/lcs.h +++ b/trunk/drivers/s390/net/lcs.h @@ -36,24 +36,6 @@ static inline int lcs_dbf_passes(debug_info_t *dbf_grp, int level) #define CARD_FROM_DEV(cdev) \ (struct lcs_card *) dev_get_drvdata( \ &((struct ccwgroup_device *)dev_get_drvdata(&cdev->dev))->dev); - -/** - * Enum for classifying detected devices. - */ -enum lcs_channel_types { - /* Device is not a channel */ - lcs_channel_type_none, - - /* Device is a 2216 channel */ - lcs_channel_type_parallel, - - /* Device is a 2216 channel */ - lcs_channel_type_2216, - - /* Device is a OSA2 card */ - lcs_channel_type_osa2 -}; - /** * CCW commands used in this driver */ diff --git a/trunk/drivers/s390/net/netiucv.c b/trunk/drivers/s390/net/netiucv.c index 395c04c2b00f..c84eadd3602a 100644 --- a/trunk/drivers/s390/net/netiucv.c +++ b/trunk/drivers/s390/net/netiucv.c @@ -741,13 +741,13 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg) if (single_flag) { if ((skb = skb_dequeue(&conn->commit_queue))) { atomic_dec(&skb->users); + dev_kfree_skb_any(skb); if (privptr) { privptr->stats.tx_packets++; privptr->stats.tx_bytes += (skb->len - NETIUCV_HDRLEN - - NETIUCV_HDRLEN); + - NETIUCV_HDRLEN); } - dev_kfree_skb_any(skb); } } conn->tx_buff->data = conn->tx_buff->head; diff --git a/trunk/drivers/serial/serial_cs.c b/trunk/drivers/serial/serial_cs.c index 7c7914f5fa02..ff4617e21426 100644 --- a/trunk/drivers/serial/serial_cs.c +++ b/trunk/drivers/serial/serial_cs.c @@ -879,10 +879,10 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "cis/DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "cis/3CXEM556.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "cis/3CXEM556.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */ - PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC710/AC750", 0xd85f6206, 0x761b11e0, "cis/SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */ - PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */ - PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */ + PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */ + PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */ + PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */ + PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */ PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "cis/MT5634ZLX.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "cis/COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"), diff --git a/trunk/drivers/ssb/scan.c b/trunk/drivers/ssb/scan.c index e8b89e8ac9bd..b74212d698c7 100644 --- a/trunk/drivers/ssb/scan.c +++ b/trunk/drivers/ssb/scan.c @@ -162,8 +162,6 @@ static u8 chipid_to_nrcores(u16 chipid) static u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx, u16 offset) { - u32 lo, hi; - switch (bus->bustype) { case SSB_BUSTYPE_SSB: offset += current_coreidx * SSB_CORE_SIZE; @@ -176,9 +174,7 @@ static u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx, offset -= 0x800; } else ssb_pcmcia_switch_segment(bus, 0); - lo = readw(bus->mmio + offset); - hi = readw(bus->mmio + offset + 2); - return lo | (hi << 16); + break; case SSB_BUSTYPE_SDIO: offset += current_coreidx * SSB_CORE_SIZE; return ssb_sdio_scan_read32(bus, offset); diff --git a/trunk/drivers/staging/Kconfig b/trunk/drivers/staging/Kconfig index 4e3873bfd010..9a4dd5992f65 100644 --- a/trunk/drivers/staging/Kconfig +++ b/trunk/drivers/staging/Kconfig @@ -131,13 +131,5 @@ source "drivers/staging/iio/Kconfig" source "drivers/staging/cowloop/Kconfig" -source "drivers/staging/strip/Kconfig" - -source "drivers/staging/arlan/Kconfig" - -source "drivers/staging/wavelan/Kconfig" - -source "drivers/staging/netwave/Kconfig" - endif # !STAGING_EXCLUDE_BUILD endif # STAGING diff --git a/trunk/drivers/staging/Makefile b/trunk/drivers/staging/Makefile index fb1d7851b563..104f2f8897ec 100644 --- a/trunk/drivers/staging/Makefile +++ b/trunk/drivers/staging/Makefile @@ -47,8 +47,3 @@ obj-$(CONFIG_RAR_REGISTER) += rar/ obj-$(CONFIG_DX_SEP) += sep/ obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_COWLOOP) += cowloop/ -obj-$(CONFIG_STRIP) += strip/ -obj-$(CONFIG_ARLAN) += arlan/ -obj-$(CONFIG_WAVELAN) += wavelan/ -obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan/ -obj-$(CONFIG_PCMCIA_NETWAVE) += netwave/ diff --git a/trunk/drivers/staging/arlan/Kconfig b/trunk/drivers/staging/arlan/Kconfig deleted file mode 100644 index 0585ed8b4d3e..000000000000 --- a/trunk/drivers/staging/arlan/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ -config ARLAN - tristate "Aironet Arlan 655 & IC2200 DS support" - depends on ISA && !64BIT - select WIRELESS_EXT - ---help--- - Aironet makes Arlan, a class of wireless LAN adapters. These use the - www.Telxon.com chip, which is also used on several similar cards. - This driver is tested on the 655 and IC2200 series cards. Look at - for the latest information. - - The driver is built as two modules, arlan and arlan-proc. The latter - is the /proc interface and is not needed most of time. - - On some computers the card ends up in non-valid state after some - time. Use a ping-reset script to clear it. diff --git a/trunk/drivers/staging/arlan/Makefile b/trunk/drivers/staging/arlan/Makefile deleted file mode 100644 index 9e58e5fae7b9..000000000000 --- a/trunk/drivers/staging/arlan/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_ARLAN) += arlan.o - -arlan-objs := arlan-main.o arlan-proc.o diff --git a/trunk/drivers/staging/arlan/TODO b/trunk/drivers/staging/arlan/TODO deleted file mode 100644 index 9bd15a2f6d9e..000000000000 --- a/trunk/drivers/staging/arlan/TODO +++ /dev/null @@ -1,7 +0,0 @@ -TODO: - - step up and maintain this driver to ensure that it continues - to work. Having the hardware for this is pretty much a - requirement. If this does not happen, the will be removed in - the 2.6.35 kernel release. - -Please send patches to Greg Kroah-Hartman . diff --git a/trunk/drivers/staging/netwave/Kconfig b/trunk/drivers/staging/netwave/Kconfig deleted file mode 100644 index c0c996c0550a..000000000000 --- a/trunk/drivers/staging/netwave/Kconfig +++ /dev/null @@ -1,11 +0,0 @@ -config PCMCIA_NETWAVE - tristate "Xircom Netwave AirSurfer Pcmcia wireless support" - depends on PCMCIA - select WIRELESS_EXT - select WEXT_PRIV - help - Say Y here if you intend to attach this type of PCMCIA (PC-card) - wireless Ethernet networking card to your computer. - - To compile this driver as a module, choose M here: the module will be - called netwave_cs. If unsure, say N. diff --git a/trunk/drivers/staging/netwave/Makefile b/trunk/drivers/staging/netwave/Makefile deleted file mode 100644 index 2ab89de59b9b..000000000000 --- a/trunk/drivers/staging/netwave/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_PCMCIA_NETWAVE) += netwave_cs.o diff --git a/trunk/drivers/staging/netwave/TODO b/trunk/drivers/staging/netwave/TODO deleted file mode 100644 index 9bd15a2f6d9e..000000000000 --- a/trunk/drivers/staging/netwave/TODO +++ /dev/null @@ -1,7 +0,0 @@ -TODO: - - step up and maintain this driver to ensure that it continues - to work. Having the hardware for this is pretty much a - requirement. If this does not happen, the will be removed in - the 2.6.35 kernel release. - -Please send patches to Greg Kroah-Hartman . diff --git a/trunk/drivers/staging/strip/Kconfig b/trunk/drivers/staging/strip/Kconfig deleted file mode 100644 index 36257b5cd6e1..000000000000 --- a/trunk/drivers/staging/strip/Kconfig +++ /dev/null @@ -1,22 +0,0 @@ -config STRIP - tristate "STRIP (Metricom starmode radio IP)" - depends on INET - select WIRELESS_EXT - ---help--- - Say Y if you have a Metricom radio and intend to use Starmode Radio - IP. STRIP is a radio protocol developed for the MosquitoNet project - to send Internet traffic using Metricom radios. Metricom radios are - small, battery powered, 100kbit/sec packet radio transceivers, about - the size and weight of a cellular telephone. (You may also have heard - them called "Metricom modems" but we avoid the term "modem" because - it misleads many people into thinking that you can plug a Metricom - modem into a phone line and use it as a modem.) - - You can use STRIP on any Linux machine with a serial port, although - it is obviously most useful for people with laptop computers. If you - think you might get a Metricom radio in the future, there is no harm - in saying Y to STRIP now, except that it makes the kernel a bit - bigger. - - To compile this as a module, choose M here: the module will be - called strip. diff --git a/trunk/drivers/staging/strip/Makefile b/trunk/drivers/staging/strip/Makefile deleted file mode 100644 index 6417bdcac2fb..000000000000 --- a/trunk/drivers/staging/strip/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_STRIP) += strip.o diff --git a/trunk/drivers/staging/strip/TODO b/trunk/drivers/staging/strip/TODO deleted file mode 100644 index 9bd15a2f6d9e..000000000000 --- a/trunk/drivers/staging/strip/TODO +++ /dev/null @@ -1,7 +0,0 @@ -TODO: - - step up and maintain this driver to ensure that it continues - to work. Having the hardware for this is pretty much a - requirement. If this does not happen, the will be removed in - the 2.6.35 kernel release. - -Please send patches to Greg Kroah-Hartman . diff --git a/trunk/drivers/staging/wavelan/Kconfig b/trunk/drivers/staging/wavelan/Kconfig deleted file mode 100644 index 786060e025c0..000000000000 --- a/trunk/drivers/staging/wavelan/Kconfig +++ /dev/null @@ -1,38 +0,0 @@ -config WAVELAN - tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support" - depends on ISA - select WIRELESS_EXT - select WEXT_SPY - select WEXT_PRIV - ---help--- - The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is - a Radio LAN (wireless Ethernet-like Local Area Network) using the - radio frequencies 900 MHz and 2.4 GHz. - - If you want to use an ISA WaveLAN card under Linux, say Y and read - the Ethernet-HOWTO, available from - . Some more specific - information is contained in - and in the source code - . - - You will also need the wireless tools package available from - . - Please read the man pages contained therein. - - To compile this driver as a module, choose M here: the module will be - called wavelan. - -config PCMCIA_WAVELAN - tristate "AT&T/Lucent old WaveLAN Pcmcia wireless support" - depends on PCMCIA - select WIRELESS_EXT - select WEXT_SPY - select WEXT_PRIV - help - Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA - (PC-card) wireless Ethernet networking card to your computer. This - driver is for the non-IEEE-802.11 Wavelan cards. - - To compile this driver as a module, choose M here: the module will be - called wavelan_cs. If unsure, say N. diff --git a/trunk/drivers/staging/wavelan/Makefile b/trunk/drivers/staging/wavelan/Makefile deleted file mode 100644 index 1cde17c69a43..000000000000 --- a/trunk/drivers/staging/wavelan/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_WAVELAN) += wavelan.o -obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan_cs.o diff --git a/trunk/drivers/staging/wavelan/TODO b/trunk/drivers/staging/wavelan/TODO deleted file mode 100644 index 9bd15a2f6d9e..000000000000 --- a/trunk/drivers/staging/wavelan/TODO +++ /dev/null @@ -1,7 +0,0 @@ -TODO: - - step up and maintain this driver to ensure that it continues - to work. Having the hardware for this is pretty much a - requirement. If this does not happen, the will be removed in - the 2.6.35 kernel release. - -Please send patches to Greg Kroah-Hartman . diff --git a/trunk/firmware/Makefile b/trunk/firmware/Makefile index 6d5c3abd06be..45c04660a44d 100644 --- a/trunk/firmware/Makefile +++ b/trunk/firmware/Makefile @@ -69,13 +69,11 @@ fw-shipped-$(CONFIG_E100) += e100/d101m_ucode.bin e100/d101s_ucode.bin \ fw-shipped-$(CONFIG_MYRI_SBUS) += myricom/lanai.bin fw-shipped-$(CONFIG_PCMCIA_PCNET) += cis/LA-PCM.cis cis/PCMLM28.cis \ cis/DP83903.cis cis/NE2K.cis \ - cis/tamarack.cis cis/PE-200.cis + cis/tamarack.cis fw-shipped-$(CONFIG_PCMCIA_3C589) += cis/3CXEM556.cis fw-shipped-$(CONFIG_PCMCIA_3C574) += cis/3CCFEM556.cis fw-shipped-$(CONFIG_SERIAL_8250_CS) += cis/MT5634ZLX.cis cis/RS-COM-2P.cis \ - cis/COMpad2.cis cis/COMpad4.cis \ - cis/SW_555_SER.cis cis/SW_7xx_SER.cis \ - cis/SW_8xx_SER.cis + cis/COMpad2.cis cis/COMpad4.cis fw-shipped-$(CONFIG_PCMCIA_SMC91C92) += ositech/Xilinx7OD.bin fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \ advansys/3550.bin advansys/38C0800.bin diff --git a/trunk/firmware/WHENCE b/trunk/firmware/WHENCE index 34b5d0a036db..a07aede9fcc3 100644 --- a/trunk/firmware/WHENCE +++ b/trunk/firmware/WHENCE @@ -600,7 +600,6 @@ File: cis/LA-PCM.cis cis/DP83903.cis cis/NE2K.cis cis/tamarack.cis - cis/PE-200.cis Licence: GPL @@ -634,9 +633,6 @@ File: cis/MT5634ZLX.cis cis/RS-COM-2P.cis cis/COMpad2.cis cis/COMpad4.cis - cis/SW_555_SER.cis - cis/SW_7xx_SER.cis - cis/SW_8xx_SER.cis Licence: GPL diff --git a/trunk/firmware/cis/PE-200.cis.ihex b/trunk/firmware/cis/PE-200.cis.ihex deleted file mode 100644 index e6dbdab6eb79..000000000000 --- a/trunk/firmware/cis/PE-200.cis.ihex +++ /dev/null @@ -1,9 +0,0 @@ -:1000000001030000FF151E0401504D582020200060 -:1000100050452D3230300045544845524E4554002D -:1000200052303100FF210206031A050101000101CF -:100030001B0EC181190155E051000F100F30FFFF59 -:040040001400FF00A9 -:00000001FF -# -# Replacement CIS for PE-200 ethernet card -# diff --git a/trunk/firmware/cis/SW_555_SER.cis.ihex b/trunk/firmware/cis/SW_555_SER.cis.ihex deleted file mode 100644 index 9b9348acee7b..000000000000 --- a/trunk/firmware/cis/SW_555_SER.cis.ihex +++ /dev/null @@ -1,12 +0,0 @@ -:100000000101FF17034100FF20043F0110072102F7 -:100010000200152A070053696572726120576972E0 -:10002000656C657373004169724361726420353594 -:1000300035004135353500526576203100FF1A050F -:1000400001030007731B0BE00118A360F8030730DE -:10005000BC3F1B08A10108A360F802071B08A2010E -:1000600008A360E803071B08A30108A360E80207D0 -:0A0070001B04A40108231400FF0084 -:00000001FF -# -# Replacement CIS for AC555 provided by Sierra Wireless -# diff --git a/trunk/firmware/cis/SW_7xx_SER.cis.ihex b/trunk/firmware/cis/SW_7xx_SER.cis.ihex deleted file mode 100644 index 11e44ad86437..000000000000 --- a/trunk/firmware/cis/SW_7xx_SER.cis.ihex +++ /dev/null @@ -1,13 +0,0 @@ -:100000000101FF17034100FF2004920110072102A4 -:1000100002001537070053696572726120576972D3 -:10002000656C6573730041433731302F4143373579 -:10003000300047505253204E6574776F726B2041E9 -:1000400064617074657200523100FF1A050103008B -:1000500007731B10E00119784D555D25A360F80367 -:100060000730BC861B08A10108A360F802071B0823 -:10007000A20108A360E803071B08A30108A360E826 -:0C00800002071B04A40108231400FF0069 -:00000001FF -# -# Replacement CIS for AC7xx provided by Sierra Wireless -# diff --git a/trunk/firmware/cis/SW_8xx_SER.cis.ihex b/trunk/firmware/cis/SW_8xx_SER.cis.ihex deleted file mode 100644 index bbcfe6348328..000000000000 --- a/trunk/firmware/cis/SW_8xx_SER.cis.ihex +++ /dev/null @@ -1,13 +0,0 @@ -:100000000101FF17034100FF2004920110072102A4 -:100010000200152F070053696572726120576972DB -:10002000656C657373004143383530003347204EAB -:100030006574776F726B20416461707465720052F1 -:100040003100FF1A0501030007731B10E001197846 -:100050004D555D25A360F8480730BC861B08A101FB -:1000600008A360F847071B08A20108A360E8480737 -:100070001B08A30108A360E847071B04A401082389 -:040080001400FF0069 -:00000001FF -# -# Replacement CIS for AC8xx provided by Sierra Wireless -# diff --git a/trunk/fs/compat_ioctl.c b/trunk/fs/compat_ioctl.c index cacf8a83e394..f91fd51b32e3 100644 --- a/trunk/fs/compat_ioctl.c +++ b/trunk/fs/compat_ioctl.c @@ -246,6 +246,428 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, unsigned return err; } +#ifdef CONFIG_NET +static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct compat_timeval __user *up = compat_ptr(arg); + struct timeval ktv; + mm_segment_t old_fs = get_fs(); + int err; + + set_fs(KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&ktv); + set_fs(old_fs); + if(!err) { + err = put_user(ktv.tv_sec, &up->tv_sec); + err |= __put_user(ktv.tv_usec, &up->tv_usec); + } + return err; +} + +static int do_siocgstampns(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct compat_timespec __user *up = compat_ptr(arg); + struct timespec kts; + mm_segment_t old_fs = get_fs(); + int err; + + set_fs(KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&kts); + set_fs(old_fs); + if (!err) { + err = put_user(kts.tv_sec, &up->tv_sec); + err |= __put_user(kts.tv_nsec, &up->tv_nsec); + } + return err; +} + +struct ifmap32 { + compat_ulong_t mem_start; + compat_ulong_t mem_end; + unsigned short base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; +}; + +struct ifreq32 { +#define IFHWADDRLEN 6 +#define IFNAMSIZ 16 + union { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + } ifr_ifrn; + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short ifru_flags; + compat_int_t ifru_ivalue; + compat_int_t ifru_mtu; + struct ifmap32 ifru_map; + char ifru_slave[IFNAMSIZ]; /* Just fits the size */ + char ifru_newname[IFNAMSIZ]; + compat_caddr_t ifru_data; + /* XXXX? ifru_settings should be here */ + } ifr_ifru; +}; + +struct ifconf32 { + compat_int_t ifc_len; /* size of buffer */ + compat_caddr_t ifcbuf; +}; + +static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ifreq __user *uifr; + int err; + + uifr = compat_alloc_user_space(sizeof(struct ifreq)); + if (copy_in_user(uifr, compat_ptr(arg), sizeof(struct ifreq32))) + return -EFAULT; + + err = sys_ioctl(fd, SIOCGIFNAME, (unsigned long)uifr); + if (err) + return err; + + if (copy_in_user(compat_ptr(arg), uifr, sizeof(struct ifreq32))) + return -EFAULT; + + return 0; +} + +static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ifconf32 ifc32; + struct ifconf ifc; + struct ifconf __user *uifc; + struct ifreq32 __user *ifr32; + struct ifreq __user *ifr; + unsigned int i, j; + int err; + + if (copy_from_user(&ifc32, compat_ptr(arg), sizeof(struct ifconf32))) + return -EFAULT; + + if (ifc32.ifcbuf == 0) { + ifc32.ifc_len = 0; + ifc.ifc_len = 0; + ifc.ifc_req = NULL; + uifc = compat_alloc_user_space(sizeof(struct ifconf)); + } else { + size_t len =((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) * + sizeof (struct ifreq); + uifc = compat_alloc_user_space(sizeof(struct ifconf) + len); + ifc.ifc_len = len; + ifr = ifc.ifc_req = (void __user *)(uifc + 1); + ifr32 = compat_ptr(ifc32.ifcbuf); + for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) { + if (copy_in_user(ifr, ifr32, sizeof(struct ifreq32))) + return -EFAULT; + ifr++; + ifr32++; + } + } + if (copy_to_user(uifc, &ifc, sizeof(struct ifconf))) + return -EFAULT; + + err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)uifc); + if (err) + return err; + + if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) + return -EFAULT; + + ifr = ifc.ifc_req; + ifr32 = compat_ptr(ifc32.ifcbuf); + for (i = 0, j = 0; + i + sizeof (struct ifreq32) <= ifc32.ifc_len && j < ifc.ifc_len; + i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) { + if (copy_in_user(ifr32, ifr, sizeof (struct ifreq32))) + return -EFAULT; + ifr32++; + ifr++; + } + + if (ifc32.ifcbuf == 0) { + /* Translate from 64-bit structure multiple to + * a 32-bit one. + */ + i = ifc.ifc_len; + i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32)); + ifc32.ifc_len = i; + } else { + ifc32.ifc_len = i; + } + if (copy_to_user(compat_ptr(arg), &ifc32, sizeof(struct ifconf32))) + return -EFAULT; + + return 0; +} + +static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ifreq __user *ifr; + struct ifreq32 __user *ifr32; + u32 data; + void __user *datap; + + ifr = compat_alloc_user_space(sizeof(*ifr)); + ifr32 = compat_ptr(arg); + + if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) + return -EFAULT; + + if (get_user(data, &ifr32->ifr_ifru.ifru_data)) + return -EFAULT; + + datap = compat_ptr(data); + if (put_user(datap, &ifr->ifr_ifru.ifru_data)) + return -EFAULT; + + return sys_ioctl(fd, cmd, (unsigned long) ifr); +} + +static int bond_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ifreq kifr; + struct ifreq __user *uifr; + struct ifreq32 __user *ifr32 = compat_ptr(arg); + mm_segment_t old_fs; + int err; + u32 data; + void __user *datap; + + switch (cmd) { + case SIOCBONDENSLAVE: + case SIOCBONDRELEASE: + case SIOCBONDSETHWADDR: + case SIOCBONDCHANGEACTIVE: + if (copy_from_user(&kifr, ifr32, sizeof(struct ifreq32))) + return -EFAULT; + + old_fs = get_fs(); + set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)&kifr); + set_fs (old_fs); + + return err; + case SIOCBONDSLAVEINFOQUERY: + case SIOCBONDINFOQUERY: + uifr = compat_alloc_user_space(sizeof(*uifr)); + if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) + return -EFAULT; + + if (get_user(data, &ifr32->ifr_ifru.ifru_data)) + return -EFAULT; + + datap = compat_ptr(data); + if (put_user(datap, &uifr->ifr_ifru.ifru_data)) + return -EFAULT; + + return sys_ioctl (fd, cmd, (unsigned long)uifr); + default: + return -EINVAL; + }; +} + +static int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ifreq __user *u_ifreq64; + struct ifreq32 __user *u_ifreq32 = compat_ptr(arg); + char tmp_buf[IFNAMSIZ]; + void __user *data64; + u32 data32; + + if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), + IFNAMSIZ)) + return -EFAULT; + if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) + return -EFAULT; + data64 = compat_ptr(data32); + + u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); + + /* Don't check these user accesses, just let that get trapped + * in the ioctl handler instead. + */ + if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], + IFNAMSIZ)) + return -EFAULT; + if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data)) + return -EFAULT; + + return sys_ioctl(fd, cmd, (unsigned long) u_ifreq64); +} + +static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ifreq ifr; + struct ifreq32 __user *uifr32; + struct ifmap32 __user *uifmap32; + mm_segment_t old_fs; + int err; + + uifr32 = compat_ptr(arg); + uifmap32 = &uifr32->ifr_ifru.ifru_map; + switch (cmd) { + case SIOCSIFMAP: + err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name)); + err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); + err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); + err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); + err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq); + err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma); + err |= __get_user(ifr.ifr_map.port, &uifmap32->port); + if (err) + return -EFAULT; + break; + case SIOCSHWTSTAMP: + if (copy_from_user(&ifr, uifr32, sizeof(*uifr32))) + return -EFAULT; + ifr.ifr_data = compat_ptr(uifr32->ifr_ifru.ifru_data); + break; + default: + if (copy_from_user(&ifr, uifr32, sizeof(*uifr32))) + return -EFAULT; + break; + } + old_fs = get_fs(); + set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)&ifr); + set_fs (old_fs); + if (!err) { + switch (cmd) { + /* TUNSETIFF is defined as _IOW, it should be _IORW + * as the data is copied back to user space, but that + * cannot be fixed without breaking all existing apps. + */ + case TUNSETIFF: + case TUNGETIFF: + case SIOCGIFFLAGS: + case SIOCGIFMETRIC: + case SIOCGIFMTU: + case SIOCGIFMEM: + case SIOCGIFHWADDR: + case SIOCGIFINDEX: + case SIOCGIFADDR: + case SIOCGIFBRDADDR: + case SIOCGIFDSTADDR: + case SIOCGIFNETMASK: + case SIOCGIFTXQLEN: + if (copy_to_user(uifr32, &ifr, sizeof(*uifr32))) + return -EFAULT; + break; + case SIOCGIFMAP: + err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); + err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); + err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); + err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); + err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq); + err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma); + err |= __put_user(ifr.ifr_map.port, &uifmap32->port); + if (err) + err = -EFAULT; + break; + } + } + return err; +} + +struct rtentry32 { + u32 rt_pad1; + struct sockaddr rt_dst; /* target address */ + struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ + struct sockaddr rt_genmask; /* target network mask (IP) */ + unsigned short rt_flags; + short rt_pad2; + u32 rt_pad3; + unsigned char rt_tos; + unsigned char rt_class; + short rt_pad4; + short rt_metric; /* +1 for binary compatibility! */ + /* char * */ u32 rt_dev; /* forcing the device at add */ + u32 rt_mtu; /* per route MTU/Window */ + u32 rt_window; /* Window clamping */ + unsigned short rt_irtt; /* Initial RTT */ + +}; + +struct in6_rtmsg32 { + struct in6_addr rtmsg_dst; + struct in6_addr rtmsg_src; + struct in6_addr rtmsg_gateway; + u32 rtmsg_type; + u16 rtmsg_dst_len; + u16 rtmsg_src_len; + u32 rtmsg_metric; + u32 rtmsg_info; + u32 rtmsg_flags; + s32 rtmsg_ifindex; +}; + +static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + int ret; + void *r = NULL; + struct in6_rtmsg r6; + struct rtentry r4; + char devname[16]; + u32 rtdev; + mm_segment_t old_fs = get_fs(); + + struct socket *mysock = sockfd_lookup(fd, &ret); + + if (mysock && mysock->sk && mysock->sk->sk_family == AF_INET6) { /* ipv6 */ + struct in6_rtmsg32 __user *ur6 = compat_ptr(arg); + ret = copy_from_user (&r6.rtmsg_dst, &(ur6->rtmsg_dst), + 3 * sizeof(struct in6_addr)); + ret |= __get_user (r6.rtmsg_type, &(ur6->rtmsg_type)); + ret |= __get_user (r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len)); + ret |= __get_user (r6.rtmsg_src_len, &(ur6->rtmsg_src_len)); + ret |= __get_user (r6.rtmsg_metric, &(ur6->rtmsg_metric)); + ret |= __get_user (r6.rtmsg_info, &(ur6->rtmsg_info)); + ret |= __get_user (r6.rtmsg_flags, &(ur6->rtmsg_flags)); + ret |= __get_user (r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); + + r = (void *) &r6; + } else { /* ipv4 */ + struct rtentry32 __user *ur4 = compat_ptr(arg); + ret = copy_from_user (&r4.rt_dst, &(ur4->rt_dst), + 3 * sizeof(struct sockaddr)); + ret |= __get_user (r4.rt_flags, &(ur4->rt_flags)); + ret |= __get_user (r4.rt_metric, &(ur4->rt_metric)); + ret |= __get_user (r4.rt_mtu, &(ur4->rt_mtu)); + ret |= __get_user (r4.rt_window, &(ur4->rt_window)); + ret |= __get_user (r4.rt_irtt, &(ur4->rt_irtt)); + ret |= __get_user (rtdev, &(ur4->rt_dev)); + if (rtdev) { + ret |= copy_from_user (devname, compat_ptr(rtdev), 15); + r4.rt_dev = devname; devname[15] = 0; + } else + r4.rt_dev = NULL; + + r = (void *) &r4; + } + + if (ret) { + ret = -EFAULT; + goto out; + } + + set_fs (KERNEL_DS); + ret = sys_ioctl (fd, cmd, (unsigned long) r); + set_fs (old_fs); + +out: + if (mysock) + sockfd_put(mysock); + + return ret; +} +#endif + #ifdef CONFIG_BLOCK typedef struct sg_io_hdr32 { compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */ @@ -790,6 +1212,170 @@ static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long a return err; } +struct atmif_sioc32 { + compat_int_t number; + compat_int_t length; + compat_caddr_t arg; +}; + +struct atm_iobuf32 { + compat_int_t length; + compat_caddr_t buffer; +}; + +#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32) +#define ATM_GETNAMES32 _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32) +#define ATM_GETTYPE32 _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32) +#define ATM_GETESI32 _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32) +#define ATM_GETADDR32 _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32) +#define ATM_RSTADDR32 _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32) +#define ATM_ADDADDR32 _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32) +#define ATM_DELADDR32 _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32) +#define ATM_GETCIRANGE32 _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32) +#define ATM_SETCIRANGE32 _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32) +#define ATM_SETESI32 _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32) +#define ATM_SETESIF32 _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32) +#define ATM_GETSTAT32 _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32) +#define ATM_GETSTATZ32 _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32) +#define ATM_GETLOOP32 _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32) +#define ATM_SETLOOP32 _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32) +#define ATM_QUERYLOOP32 _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32) + +static struct { + unsigned int cmd32; + unsigned int cmd; +} atm_ioctl_map[] = { + { ATM_GETLINKRATE32, ATM_GETLINKRATE }, + { ATM_GETNAMES32, ATM_GETNAMES }, + { ATM_GETTYPE32, ATM_GETTYPE }, + { ATM_GETESI32, ATM_GETESI }, + { ATM_GETADDR32, ATM_GETADDR }, + { ATM_RSTADDR32, ATM_RSTADDR }, + { ATM_ADDADDR32, ATM_ADDADDR }, + { ATM_DELADDR32, ATM_DELADDR }, + { ATM_GETCIRANGE32, ATM_GETCIRANGE }, + { ATM_SETCIRANGE32, ATM_SETCIRANGE }, + { ATM_SETESI32, ATM_SETESI }, + { ATM_SETESIF32, ATM_SETESIF }, + { ATM_GETSTAT32, ATM_GETSTAT }, + { ATM_GETSTATZ32, ATM_GETSTATZ }, + { ATM_GETLOOP32, ATM_GETLOOP }, + { ATM_SETLOOP32, ATM_SETLOOP }, + { ATM_QUERYLOOP32, ATM_QUERYLOOP } +}; + +#define NR_ATM_IOCTL ARRAY_SIZE(atm_ioctl_map) + +static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct atm_iobuf __user *iobuf; + struct atm_iobuf32 __user *iobuf32; + u32 data; + void __user *datap; + int len, err; + + iobuf = compat_alloc_user_space(sizeof(*iobuf)); + iobuf32 = compat_ptr(arg); + + if (get_user(len, &iobuf32->length) || + get_user(data, &iobuf32->buffer)) + return -EFAULT; + datap = compat_ptr(data); + if (put_user(len, &iobuf->length) || + put_user(datap, &iobuf->buffer)) + return -EFAULT; + + err = sys_ioctl(fd, cmd, (unsigned long)iobuf); + + if (!err) { + if (copy_in_user(&iobuf32->length, &iobuf->length, + sizeof(int))) + err = -EFAULT; + } + + return err; +} + +static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct atmif_sioc __user *sioc; + struct atmif_sioc32 __user *sioc32; + u32 data; + void __user *datap; + int err; + + sioc = compat_alloc_user_space(sizeof(*sioc)); + sioc32 = compat_ptr(arg); + + if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) || + get_user(data, &sioc32->arg)) + return -EFAULT; + datap = compat_ptr(data); + if (put_user(datap, &sioc->arg)) + return -EFAULT; + + err = sys_ioctl(fd, cmd, (unsigned long) sioc); + + if (!err) { + if (copy_in_user(&sioc32->length, &sioc->length, + sizeof(int))) + err = -EFAULT; + } + return err; +} + +static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) +{ + int i; + unsigned int cmd = 0; + + switch (cmd32) { + case SONET_GETSTAT: + case SONET_GETSTATZ: + case SONET_GETDIAG: + case SONET_SETDIAG: + case SONET_CLRDIAG: + case SONET_SETFRAMING: + case SONET_GETFRAMING: + case SONET_GETFRSENSE: + return do_atmif_sioc(fd, cmd32, arg); + } + + for (i = 0; i < NR_ATM_IOCTL; i++) { + if (cmd32 == atm_ioctl_map[i].cmd32) { + cmd = atm_ioctl_map[i].cmd; + break; + } + } + if (i == NR_ATM_IOCTL) + return -EINVAL; + + switch (cmd) { + case ATM_GETNAMES: + return do_atm_iobuf(fd, cmd, arg); + + case ATM_GETLINKRATE: + case ATM_GETTYPE: + case ATM_GETESI: + case ATM_GETADDR: + case ATM_RSTADDR: + case ATM_ADDADDR: + case ATM_DELADDR: + case ATM_GETCIRANGE: + case ATM_SETCIRANGE: + case ATM_SETESI: + case ATM_SETESIF: + case ATM_GETSTAT: + case ATM_GETSTATZ: + case ATM_GETLOOP: + case ATM_SETLOOP: + case ATM_QUERYLOOP: + return do_atmif_sioc(fd, cmd, arg); + } + + return -EINVAL; +} + static __used int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) { @@ -1132,6 +1718,21 @@ static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, unsigned long a return sys_ioctl(fd, cmd, (unsigned long)tdata); } +/* Since old style bridge ioctl's endup using SIOCDEVPRIVATE + * for some operations; this forces use of the newer bridge-utils that + * use compatible ioctls + */ +static int old_bridge_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + u32 tmp; + + if (get_user(tmp, (u32 __user *) arg)) + return -EFAULT; + if (tmp == BRCTL_GET_VERSION) + return BRCTL_VERSION + 1; + return -EINVAL; +} + #define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) #define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t) #define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) @@ -1378,6 +1979,18 @@ COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) #endif +/* Big T */ +COMPATIBLE_IOCTL(TUNSETNOCSUM) +COMPATIBLE_IOCTL(TUNSETDEBUG) +COMPATIBLE_IOCTL(TUNSETPERSIST) +COMPATIBLE_IOCTL(TUNSETOWNER) +COMPATIBLE_IOCTL(TUNSETLINK) +COMPATIBLE_IOCTL(TUNSETGROUP) +COMPATIBLE_IOCTL(TUNGETFEATURES) +COMPATIBLE_IOCTL(TUNSETOFFLOAD) +COMPATIBLE_IOCTL(TUNSETTXFILTER) +COMPATIBLE_IOCTL(TUNGETSNDBUF) +COMPATIBLE_IOCTL(TUNSETSNDBUF) /* Big V */ COMPATIBLE_IOCTL(VT_SETMODE) COMPATIBLE_IOCTL(VT_GETMODE) @@ -1419,6 +2032,30 @@ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ COMPATIBLE_IOCTL(MTIOCTOP) /* Socket level stuff */ COMPATIBLE_IOCTL(FIOQSIZE) +COMPATIBLE_IOCTL(FIOSETOWN) +COMPATIBLE_IOCTL(SIOCSPGRP) +COMPATIBLE_IOCTL(FIOGETOWN) +COMPATIBLE_IOCTL(SIOCGPGRP) +COMPATIBLE_IOCTL(SIOCATMARK) +COMPATIBLE_IOCTL(SIOCSIFLINK) +COMPATIBLE_IOCTL(SIOCSIFENCAP) +COMPATIBLE_IOCTL(SIOCGIFENCAP) +COMPATIBLE_IOCTL(SIOCSIFNAME) +COMPATIBLE_IOCTL(SIOCSARP) +COMPATIBLE_IOCTL(SIOCGARP) +COMPATIBLE_IOCTL(SIOCDARP) +COMPATIBLE_IOCTL(SIOCSRARP) +COMPATIBLE_IOCTL(SIOCGRARP) +COMPATIBLE_IOCTL(SIOCDRARP) +COMPATIBLE_IOCTL(SIOCADDDLCI) +COMPATIBLE_IOCTL(SIOCDELDLCI) +COMPATIBLE_IOCTL(SIOCGMIIPHY) +COMPATIBLE_IOCTL(SIOCGMIIREG) +COMPATIBLE_IOCTL(SIOCSMIIREG) +COMPATIBLE_IOCTL(SIOCGIFVLAN) +COMPATIBLE_IOCTL(SIOCSIFVLAN) +COMPATIBLE_IOCTL(SIOCBRADDBR) +COMPATIBLE_IOCTL(SIOCBRDELBR) #ifdef CONFIG_BLOCK /* SG stuff */ COMPATIBLE_IOCTL(SG_SET_TIMEOUT) @@ -1674,6 +2311,22 @@ COMPATIBLE_IOCTL(RAW_SETBIND) COMPATIBLE_IOCTL(RAW_GETBIND) /* SMB ioctls which do not need any translations */ COMPATIBLE_IOCTL(SMB_IOC_NEWCONN) +/* Little a */ +COMPATIBLE_IOCTL(ATMSIGD_CTRL) +COMPATIBLE_IOCTL(ATMARPD_CTRL) +COMPATIBLE_IOCTL(ATMLEC_CTRL) +COMPATIBLE_IOCTL(ATMLEC_MCAST) +COMPATIBLE_IOCTL(ATMLEC_DATA) +COMPATIBLE_IOCTL(ATM_SETSC) +COMPATIBLE_IOCTL(SIOCSIFATMTCP) +COMPATIBLE_IOCTL(SIOCMKCLIP) +COMPATIBLE_IOCTL(ATMARP_MKIP) +COMPATIBLE_IOCTL(ATMARP_SETENTRY) +COMPATIBLE_IOCTL(ATMARP_ENCAP) +COMPATIBLE_IOCTL(ATMTCP_CREATE) +COMPATIBLE_IOCTL(ATMTCP_REMOVE) +COMPATIBLE_IOCTL(ATMMPC_CTRL) +COMPATIBLE_IOCTL(ATMMPC_DATA) /* Watchdog */ COMPATIBLE_IOCTL(WDIOC_GETSUPPORT) COMPATIBLE_IOCTL(WDIOC_GETSTATUS) @@ -1879,6 +2532,63 @@ COMPATIBLE_IOCTL(JSIOCGBUTTONS) COMPATIBLE_IOCTL(JSIOCGNAME(0)) /* now things that need handlers */ +#ifdef CONFIG_NET +HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32) +HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf) +HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFMETRIC, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFMETRIC, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFMTU, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFMTU, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFMEM, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFMEM, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFHWADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFHWADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCADDMULTI, dev_ifsioc) +HANDLE_IOCTL(SIOCDELMULTI, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFINDEX, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFHWBROADCAST, dev_ifsioc) +HANDLE_IOCTL(SIOCSHWTSTAMP, dev_ifsioc) + +/* ioctls used by appletalk ddp.c */ +HANDLE_IOCTL(SIOCATALKDIFADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCDIFADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSARP, dev_ifsioc) +HANDLE_IOCTL(SIOCDARP, dev_ifsioc) + +HANDLE_IOCTL(SIOCGIFBRDADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFBRDADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFDSTADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFDSTADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFNETMASK, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc) +HANDLE_IOCTL(TUNSETIFF, dev_ifsioc) +HANDLE_IOCTL(TUNGETIFF, dev_ifsioc) +HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl) +HANDLE_IOCTL(SIOCBONDENSLAVE, bond_ioctl) +HANDLE_IOCTL(SIOCBONDRELEASE, bond_ioctl) +HANDLE_IOCTL(SIOCBONDSETHWADDR, bond_ioctl) +HANDLE_IOCTL(SIOCBONDSLAVEINFOQUERY, bond_ioctl) +HANDLE_IOCTL(SIOCBONDINFOQUERY, bond_ioctl) +HANDLE_IOCTL(SIOCBONDCHANGEACTIVE, bond_ioctl) +HANDLE_IOCTL(SIOCADDRT, routing_ioctl) +HANDLE_IOCTL(SIOCDELRT, routing_ioctl) +HANDLE_IOCTL(SIOCBRADDIF, dev_ifsioc) +HANDLE_IOCTL(SIOCBRDELIF, dev_ifsioc) +/* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */ +HANDLE_IOCTL(SIOCRTMSG, ret_einval) +HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) +HANDLE_IOCTL(SIOCGSTAMPNS, do_siocgstampns) +#endif #ifdef CONFIG_BLOCK HANDLE_IOCTL(SG_IO,sg_ioctl_trans) HANDLE_IOCTL(SG_GET_REQUEST_TABLE, sg_grt_trans) @@ -1903,6 +2613,31 @@ HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl) /* One SMB ioctl needs translations. */ #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t) HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid) +HANDLE_IOCTL(ATM_GETLINKRATE32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETNAMES32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETTYPE32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETESI32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETADDR32, do_atm_ioctl) +HANDLE_IOCTL(ATM_RSTADDR32, do_atm_ioctl) +HANDLE_IOCTL(ATM_ADDADDR32, do_atm_ioctl) +HANDLE_IOCTL(ATM_DELADDR32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETCIRANGE32, do_atm_ioctl) +HANDLE_IOCTL(ATM_SETCIRANGE32, do_atm_ioctl) +HANDLE_IOCTL(ATM_SETESI32, do_atm_ioctl) +HANDLE_IOCTL(ATM_SETESIF32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETSTAT32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETSTATZ32, do_atm_ioctl) +HANDLE_IOCTL(ATM_GETLOOP32, do_atm_ioctl) +HANDLE_IOCTL(ATM_SETLOOP32, do_atm_ioctl) +HANDLE_IOCTL(ATM_QUERYLOOP32, do_atm_ioctl) +HANDLE_IOCTL(SONET_GETSTAT, do_atm_ioctl) +HANDLE_IOCTL(SONET_GETSTATZ, do_atm_ioctl) +HANDLE_IOCTL(SONET_GETDIAG, do_atm_ioctl) +HANDLE_IOCTL(SONET_SETDIAG, do_atm_ioctl) +HANDLE_IOCTL(SONET_CLRDIAG, do_atm_ioctl) +HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl) +HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl) +HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) /* block stuff */ #ifdef CONFIG_BLOCK /* loop */ @@ -1937,7 +2672,11 @@ COMPATIBLE_IOCTL(USBDEVFS_IOCTL32) HANDLE_IOCTL(I2C_FUNCS, w_long) HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl) HANDLE_IOCTL(I2C_SMBUS, do_i2c_smbus_ioctl) +/* bridge */ +HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl) +HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl) /* Not implemented in the native kernel */ +IGNORE_IOCTL(SIOCGIFCOUNT) HANDLE_IOCTL(RTC_IRQP_READ32, rtc_ioctl) HANDLE_IOCTL(RTC_IRQP_SET32, rtc_ioctl) HANDLE_IOCTL(RTC_EPOCH_READ32, rtc_ioctl) @@ -2092,6 +2831,12 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, goto found_handler; } +#ifdef CONFIG_NET + if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) && + cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { + error = siocdevprivate_ioctl(fd, cmd, arg); + } else +#endif { static int count; diff --git a/trunk/include/linux/can/core.h b/trunk/include/linux/can/core.h index 6c507bea275f..25085cbadcfc 100644 --- a/trunk/include/linux/can/core.h +++ b/trunk/include/linux/can/core.h @@ -32,12 +32,14 @@ * struct can_proto - CAN protocol structure * @type: type argument in socket() syscall, e.g. SOCK_DGRAM. * @protocol: protocol number in socket() syscall. + * @capability: capability needed to open the socket, or -1 for no restriction. * @ops: pointer to struct proto_ops for sock->ops. * @prot: pointer to struct proto structure. */ struct can_proto { int type; int protocol; + int capability; struct proto_ops *ops; struct proto *prot; }; diff --git a/trunk/include/linux/can/platform/mcp251x.h b/trunk/include/linux/can/platform/mcp251x.h deleted file mode 100644 index 1448177d86d5..000000000000 --- a/trunk/include/linux/can/platform/mcp251x.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __CAN_PLATFORM_MCP251X_H__ -#define __CAN_PLATFORM_MCP251X_H__ - -/* - * - * CAN bus driver for Microchip 251x CAN Controller with SPI Interface - * - */ - -#include - -/** - * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data - * @oscillator_frequency: - oscillator frequency in Hz - * @model: - actual type of chip - * @board_specific_setup: - called before probing the chip (power,reset) - * @transceiver_enable: - called to power on/off the transceiver - * @power_enable: - called to power on/off the mcp *and* the - * transceiver - * - * Please note that you should define power_enable or transceiver_enable or - * none of them. Defining both of them is no use. - * - */ - -struct mcp251x_platform_data { - unsigned long oscillator_frequency; - int model; -#define CAN_MCP251X_MCP2510 0 -#define CAN_MCP251X_MCP2515 1 - int (*board_specific_setup)(struct spi_device *spi); - int (*transceiver_enable)(int enable); - int (*power_enable) (int enable); -}; - -#endif /* __CAN_PLATFORM_MCP251X_H__ */ diff --git a/trunk/include/linux/compat.h b/trunk/include/linux/compat.h index ef68119a4fd2..af931ee43dd8 100644 --- a/trunk/include/linux/compat.h +++ b/trunk/include/linux/compat.h @@ -10,8 +10,6 @@ #include #include /* for HZ */ #include -#include -#include #include #include @@ -156,48 +154,6 @@ typedef struct compat_sigevent { } _sigev_un; } compat_sigevent_t; -struct compat_ifmap { - compat_ulong_t mem_start; - compat_ulong_t mem_end; - unsigned short base_addr; - unsigned char irq; - unsigned char dma; - unsigned char port; -}; - -struct compat_if_settings -{ - unsigned int type; /* Type of physical device or protocol */ - unsigned int size; /* Size of the data allocated by the caller */ - compat_uptr_t ifs_ifsu; /* union of pointers */ -}; - -struct compat_ifreq { - union { - char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ - } ifr_ifrn; - union { - struct sockaddr ifru_addr; - struct sockaddr ifru_dstaddr; - struct sockaddr ifru_broadaddr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; - short ifru_flags; - compat_int_t ifru_ivalue; - compat_int_t ifru_mtu; - struct compat_ifmap ifru_map; - char ifru_slave[IFNAMSIZ]; /* Just fits the size */ - char ifru_newname[IFNAMSIZ]; - compat_caddr_t ifru_data; - struct compat_if_settings ifru_settings; - } ifr_ifru; -}; - -struct compat_ifconf { - compat_int_t ifc_len; /* size of buffer */ - compat_caddr_t ifcbuf; -}; - struct compat_robust_list { compat_uptr_t next; }; diff --git a/trunk/include/linux/ieee80211.h b/trunk/include/linux/ieee80211.h index 0aa831467493..52e15e079c61 100644 --- a/trunk/include/linux/ieee80211.h +++ b/trunk/include/linux/ieee80211.h @@ -472,7 +472,7 @@ static inline int ieee80211_is_cfendack(__le16 fc) } /** - * ieee80211_is_nullfunc - check if frame is a regular (non-QoS) nullfunc frame + * ieee80211_is_nullfunc - check if FTYPE=IEEE80211_FTYPE_DATA and STYPE=IEEE80211_STYPE_NULLFUNC * @fc: frame control bytes in little-endian byteorder */ static inline int ieee80211_is_nullfunc(__le16 fc) @@ -481,16 +481,6 @@ static inline int ieee80211_is_nullfunc(__le16 fc) cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC); } -/** - * ieee80211_is_qos_nullfunc - check if frame is a QoS nullfunc frame - * @fc: frame control bytes in little-endian byteorder - */ -static inline int ieee80211_is_qos_nullfunc(__le16 fc) -{ - return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); -} - struct ieee80211s_hdr { u8 flags; u8 ttl; diff --git a/trunk/include/linux/mmc/sdio_ids.h b/trunk/include/linux/mmc/sdio_ids.h index 33b2ea09a4ad..2dbfb5a05994 100644 --- a/trunk/include/linux/mmc/sdio_ids.h +++ b/trunk/include/linux/mmc/sdio_ids.h @@ -28,7 +28,6 @@ #define SDIO_DEVICE_ID_INTEL_IWMC3200TOP 0x1404 #define SDIO_DEVICE_ID_INTEL_IWMC3200GPS 0x1405 #define SDIO_DEVICE_ID_INTEL_IWMC3200BT 0x1406 -#define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5 0x1407 #define SDIO_VENDOR_ID_MARVELL 0x02df #define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103 diff --git a/trunk/include/linux/net.h b/trunk/include/linux/net.h index 6ce87663551c..4da9d571b053 100644 --- a/trunk/include/linux/net.h +++ b/trunk/include/linux/net.h @@ -204,8 +204,7 @@ struct proto_ops { struct net_proto_family { int family; - int (*create)(struct net *net, struct socket *sock, - int protocol, int kern); + int (*create)(struct net *net, struct socket *sock, int protocol); struct module *owner; }; @@ -268,6 +267,89 @@ extern int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg); extern int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how); +#ifndef CONFIG_SMP +#define SOCKOPS_WRAPPED(name) name +#define SOCKOPS_WRAP(name, fam) +#else + +#define SOCKOPS_WRAPPED(name) __unlocked_##name + +#define SOCKCALL_WRAP(name, call, parms, args) \ +static int __lock_##name##_##call parms \ +{ \ + int ret; \ + lock_kernel(); \ + ret = __unlocked_##name##_ops.call args ;\ + unlock_kernel(); \ + return ret; \ +} + +#define SOCKCALL_UWRAP(name, call, parms, args) \ +static unsigned int __lock_##name##_##call parms \ +{ \ + int ret; \ + lock_kernel(); \ + ret = __unlocked_##name##_ops.call args ;\ + unlock_kernel(); \ + return ret; \ +} + + +#define SOCKOPS_WRAP(name, fam) \ +SOCKCALL_WRAP(name, release, (struct socket *sock), (sock)) \ +SOCKCALL_WRAP(name, bind, (struct socket *sock, struct sockaddr *uaddr, int addr_len), \ + (sock, uaddr, addr_len)) \ +SOCKCALL_WRAP(name, connect, (struct socket *sock, struct sockaddr * uaddr, \ + int addr_len, int flags), \ + (sock, uaddr, addr_len, flags)) \ +SOCKCALL_WRAP(name, socketpair, (struct socket *sock1, struct socket *sock2), \ + (sock1, sock2)) \ +SOCKCALL_WRAP(name, accept, (struct socket *sock, struct socket *newsock, \ + int flags), (sock, newsock, flags)) \ +SOCKCALL_WRAP(name, getname, (struct socket *sock, struct sockaddr *uaddr, \ + int *addr_len, int peer), (sock, uaddr, addr_len, peer)) \ +SOCKCALL_UWRAP(name, poll, (struct file *file, struct socket *sock, struct poll_table_struct *wait), \ + (file, sock, wait)) \ +SOCKCALL_WRAP(name, ioctl, (struct socket *sock, unsigned int cmd, \ + unsigned long arg), (sock, cmd, arg)) \ +SOCKCALL_WRAP(name, compat_ioctl, (struct socket *sock, unsigned int cmd, \ + unsigned long arg), (sock, cmd, arg)) \ +SOCKCALL_WRAP(name, listen, (struct socket *sock, int len), (sock, len)) \ +SOCKCALL_WRAP(name, shutdown, (struct socket *sock, int flags), (sock, flags)) \ +SOCKCALL_WRAP(name, setsockopt, (struct socket *sock, int level, int optname, \ + char __user *optval, unsigned int optlen), (sock, level, optname, optval, optlen)) \ +SOCKCALL_WRAP(name, getsockopt, (struct socket *sock, int level, int optname, \ + char __user *optval, int __user *optlen), (sock, level, optname, optval, optlen)) \ +SOCKCALL_WRAP(name, sendmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len), \ + (iocb, sock, m, len)) \ +SOCKCALL_WRAP(name, recvmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len, int flags), \ + (iocb, sock, m, len, flags)) \ +SOCKCALL_WRAP(name, mmap, (struct file *file, struct socket *sock, struct vm_area_struct *vma), \ + (file, sock, vma)) \ + \ +static const struct proto_ops name##_ops = { \ + .family = fam, \ + .owner = THIS_MODULE, \ + .release = __lock_##name##_release, \ + .bind = __lock_##name##_bind, \ + .connect = __lock_##name##_connect, \ + .socketpair = __lock_##name##_socketpair, \ + .accept = __lock_##name##_accept, \ + .getname = __lock_##name##_getname, \ + .poll = __lock_##name##_poll, \ + .ioctl = __lock_##name##_ioctl, \ + .compat_ioctl = __lock_##name##_compat_ioctl, \ + .listen = __lock_##name##_listen, \ + .shutdown = __lock_##name##_shutdown, \ + .setsockopt = __lock_##name##_setsockopt, \ + .getsockopt = __lock_##name##_getsockopt, \ + .sendmsg = __lock_##name##_sendmsg, \ + .recvmsg = __lock_##name##_recvmsg, \ + .mmap = __lock_##name##_mmap, \ +}; + +#endif + #define MODULE_ALIAS_NETPROTO(proto) \ MODULE_ALIAS("net-pf-" __stringify(proto)) diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index 61425d0c6123..465add6c43e3 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -63,48 +63,27 @@ struct wireless_dev; #define HAVE_FREE_NETDEV /* free_netdev() */ #define HAVE_NETDEV_PRIV /* netdev_priv() */ -/* - * Transmit return codes: transmit return codes originate from three different - * namespaces: - * - * - qdisc return codes - * - driver transmit return codes - * - errno values - * - * Drivers are allowed to return any one of those in their hard_start_xmit() - * function. Real network devices commonly used with qdiscs should only return - * the driver transmit return codes though - when qdiscs are used, the actual - * transmission happens asynchronously, so the value is not propagated to - * higher layers. Virtual network devices transmit synchronously, in this case - * the driver transmit return codes are consumed by dev_queue_xmit(), all - * others are propagated to higher layers. - */ - -/* qdisc ->enqueue() return codes. */ -#define NET_XMIT_SUCCESS 0x00 -#define NET_XMIT_DROP 0x10 /* skb dropped */ -#define NET_XMIT_CN 0x20 /* congestion notification */ -#define NET_XMIT_POLICED 0x30 /* skb is shot by police */ -#define NET_XMIT_MASK 0xf0 /* qdisc flags in net/sch_generic.h */ +#define NET_XMIT_SUCCESS 0 +#define NET_XMIT_DROP 1 /* skb dropped */ +#define NET_XMIT_CN 2 /* congestion notification */ +#define NET_XMIT_POLICED 3 /* skb is shot by police */ +#define NET_XMIT_MASK 0xFFFF /* qdisc flags in net/sch_generic.h */ /* Backlog congestion levels */ -#define NET_RX_SUCCESS 0 /* keep 'em coming, baby */ -#define NET_RX_DROP 1 /* packet dropped */ +#define NET_RX_SUCCESS 0 /* keep 'em coming, baby */ +#define NET_RX_DROP 1 /* packet dropped */ /* NET_XMIT_CN is special. It does not guarantee that this packet is lost. It * indicates that the device will soon be dropping packets, or already drops * some packets of the same priority; prompting us to send less aggressively. */ -#define net_xmit_eval(e) ((e) == NET_XMIT_CN ? 0 : (e)) +#define net_xmit_eval(e) ((e) == NET_XMIT_CN? 0 : (e)) #define net_xmit_errno(e) ((e) != NET_XMIT_CN ? -ENOBUFS : 0) /* Driver transmit return codes */ -#define NETDEV_TX_MASK 0xf - enum netdev_tx { - __NETDEV_TX_MIN = INT_MIN, /* make sure enum is signed */ - NETDEV_TX_OK = 0, /* driver took care of packet */ - NETDEV_TX_BUSY = 1, /* driver tx path was busy*/ - NETDEV_TX_LOCKED = 2, /* driver tx lock was already taken */ + NETDEV_TX_OK = 0, /* driver took care of packet */ + NETDEV_TX_BUSY, /* driver tx path was busy*/ + NETDEV_TX_LOCKED = -1, /* driver tx lock was already taken */ }; typedef enum netdev_tx netdev_tx_t; @@ -1100,8 +1079,6 @@ extern rwlock_t dev_base_lock; /* Device list lock */ list_for_each_entry_safe(d, n, &(net)->dev_base_head, dev_list) #define for_each_netdev_continue(net, d) \ list_for_each_entry_continue(d, &(net)->dev_base_head, dev_list) -#define for_each_netdev_continue_rcu(net, d) \ - list_for_each_entry_continue_rcu(d, &(net)->dev_base_head, dev_list) #define net_device_entry(lh) list_entry(lh, struct net_device, dev_list) static inline struct net_device *next_net_device(struct net_device *dev) @@ -1114,16 +1091,6 @@ static inline struct net_device *next_net_device(struct net_device *dev) return lh == &net->dev_base_head ? NULL : net_device_entry(lh); } -static inline struct net_device *next_net_device_rcu(struct net_device *dev) -{ - struct list_head *lh; - struct net *net; - - net = dev_net(dev); - lh = rcu_dereference(dev->dev_list.next); - return lh == &net->dev_base_head ? NULL : net_device_entry(lh); -} - static inline struct net_device *first_net_device(struct net *net) { return list_empty(&net->dev_base_head) ? NULL : diff --git a/trunk/include/linux/rculist.h b/trunk/include/linux/rculist.h index 1bf0f708c4fc..5710f43bbc9e 100644 --- a/trunk/include/linux/rculist.h +++ b/trunk/include/linux/rculist.h @@ -261,20 +261,6 @@ static inline void list_splice_init_rcu(struct list_head *list, prefetch((pos)->next), (pos) != (head); \ (pos) = rcu_dereference((pos)->next)) -/** - * list_for_each_entry_continue_rcu - continue iteration over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Continue to iterate over list of given type, continuing after - * the current position. - */ -#define list_for_each_entry_continue_rcu(pos, head, member) \ - for (pos = list_entry_rcu(pos->member.next, typeof(*pos), member); \ - prefetch(pos->member.next), &pos->member != (head); \ - pos = list_entry_rcu(pos->member.next, typeof(*pos), member)) - /** * hlist_del_rcu - deletes entry from hash list without re-initialization * @n: the element to delete from the hash list. diff --git a/trunk/include/linux/skbuff.h b/trunk/include/linux/skbuff.h index 63f47426977a..d0448c5d1ffc 100644 --- a/trunk/include/linux/skbuff.h +++ b/trunk/include/linux/skbuff.h @@ -354,8 +354,8 @@ struct sk_buff { ipvs_property:1, peeked:1, nf_trace:1; - __be16 protocol:16; kmemcheck_bitfield_end(flags1); + __be16 protocol; void (*destructor)(struct sk_buff *skb); #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) @@ -367,6 +367,7 @@ struct sk_buff { #endif int iif; + __u16 queue_mapping; #ifdef CONFIG_NET_SCHED __u16 tc_index; /* traffic control index */ #ifdef CONFIG_NET_CLS_ACT @@ -375,7 +376,6 @@ struct sk_buff { #endif kmemcheck_bitfield_begin(flags2); - __u16 queue_mapping:16; #ifdef CONFIG_IPV6_NDISC_NODETYPE __u8 ndisc_nodetype:2; #endif @@ -1768,8 +1768,6 @@ extern int skb_copy_datagram_const_iovec(const struct sk_buff *from, int to_offset, int size); extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb); -extern void skb_free_datagram_locked(struct sock *sk, - struct sk_buff *skb); extern int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags); extern __wsum skb_checksum(const struct sk_buff *skb, int offset, diff --git a/trunk/include/linux/tcp.h b/trunk/include/linux/tcp.h index 32d7d77b4a01..eeecb8547a2a 100644 --- a/trunk/include/linux/tcp.h +++ b/trunk/include/linux/tcp.h @@ -81,12 +81,6 @@ enum { TCP_DATA_OFFSET = __cpu_to_be32(0xF0000000) }; -/* - * TCP general constants - */ -#define TCP_MSS_DEFAULT 536U /* IPv4 (RFC1122, RFC2581) */ -#define TCP_MSS_DESIRED 1220U /* IPv6 (tunneled), EDNS0 (RFC3226) */ - /* TCP socket options */ #define TCP_NODELAY 1 /* Turn off Nagle's algorithm. */ #define TCP_MAXSEG 2 /* Limit MSS */ diff --git a/trunk/include/linux/udp.h b/trunk/include/linux/udp.h index 03f72a2ba028..832361e3e596 100644 --- a/trunk/include/linux/udp.h +++ b/trunk/include/linux/udp.h @@ -55,9 +55,6 @@ static inline int udp_hashfn(struct net *net, unsigned num, unsigned mask) struct udp_sock { /* inet_sock has to be the first member */ struct inet_sock inet; -#define udp_port_hash inet.sk.__sk_common.skc_u16hashes[0] -#define udp_portaddr_hash inet.sk.__sk_common.skc_u16hashes[1] -#define udp_portaddr_node inet.sk.__sk_common.skc_portaddr_node int pending; /* Any pending frames ? */ unsigned int corkflag; /* Cork is required */ __u16 encap_type; /* Is this an Encapsulation socket? */ @@ -88,12 +85,6 @@ static inline struct udp_sock *udp_sk(const struct sock *sk) return (struct udp_sock *)sk; } -#define udp_portaddr_for_each_entry(__sk, node, list) \ - hlist_nulls_for_each_entry(__sk, node, list, __sk_common.skc_portaddr_node) - -#define udp_portaddr_for_each_entry_rcu(__sk, node, list) \ - hlist_nulls_for_each_entry_rcu(__sk, node, list, __sk_common.skc_portaddr_node) - #define IS_UDPLITE(__sk) (udp_sk(__sk)->pcflag) #endif diff --git a/trunk/include/linux/usb/usbnet.h b/trunk/include/linux/usb/usbnet.h index 8c84881f8478..86c31b753266 100644 --- a/trunk/include/linux/usb/usbnet.h +++ b/trunk/include/linux/usb/usbnet.h @@ -92,7 +92,6 @@ struct driver_info { #define FLAG_SEND_ZLP 0x0200 /* hw requires ZLPs are sent */ #define FLAG_WWAN 0x0400 /* use "wwan%d" names */ -#define FLAG_LINK_INTR 0x0800 /* updates link (carrier) status */ /* init device ... can sleep, or cause probe() failure */ int (*bind)(struct usbnet *, struct usb_interface *); diff --git a/trunk/include/linux/wimax/debug.h b/trunk/include/linux/wimax/debug.h index db8096e88533..c703e0340423 100644 --- a/trunk/include/linux/wimax/debug.h +++ b/trunk/include/linux/wimax/debug.h @@ -450,76 +450,4 @@ do { \ }) -static inline -void d_submodule_set(struct d_level *d_level, size_t d_level_size, - const char *submodule, u8 level, const char *tag) -{ - struct d_level *itr, *top; - int index = -1; - - for (itr = d_level, top = itr + d_level_size; itr < top; itr++) { - index++; - if (itr->name == NULL) { - printk(KERN_ERR "%s: itr->name NULL?? (%p, #%d)\n", - tag, itr, index); - continue; - } - if (!strcmp(itr->name, submodule)) { - itr->level = level; - return; - } - } - printk(KERN_ERR "%s: unknown submodule %s\n", tag, submodule); -} - - -/** - * d_parse_params - Parse a string with debug parameters from the - * command line - * - * @d_level: level structure (D_LEVEL) - * @d_level_size: number of items in the level structure - * (D_LEVEL_SIZE). - * @_params: string with the parameters; this is a space (not tab!) - * separated list of NAME:VALUE, where value is the debug level - * and NAME is the name of the submodule. - * @tag: string for error messages (example: MODULE.ARGNAME). - */ -static inline -void d_parse_params(struct d_level *d_level, size_t d_level_size, - const char *_params, const char *tag) -{ - char submodule[130], *params, *params_orig, *token, *colon; - unsigned level, tokens; - - if (_params == NULL) - return; - params_orig = kstrdup(_params, GFP_KERNEL); - params = params_orig; - while (1) { - token = strsep(¶ms, " "); - if (token == NULL) - break; - if (*token == '\0') /* eat joint spaces */ - continue; - /* kernel's sscanf %s eats until whitespace, so we - * replace : by \n so it doesn't get eaten later by - * strsep */ - colon = strchr(token, ':'); - if (colon != NULL) - *colon = '\n'; - tokens = sscanf(token, "%s\n%u", submodule, &level); - if (colon != NULL) - *colon = ':'; /* set back, for error messages */ - if (tokens == 2) - d_submodule_set(d_level, d_level_size, - submodule, level, tag); - else - printk(KERN_ERR "%s: can't parse '%s' as a " - "SUBMODULE:LEVEL (%d tokens)\n", - tag, token, tokens); - } - kfree(params_orig); -} - #endif /* #ifndef __debug__h__ */ diff --git a/trunk/include/linux/wimax/i2400m.h b/trunk/include/linux/wimax/i2400m.h index 62d356153565..433693ef2bb0 100644 --- a/trunk/include/linux/wimax/i2400m.h +++ b/trunk/include/linux/wimax/i2400m.h @@ -138,7 +138,7 @@ struct i2400m_bcf_hdr { __le32 module_id; __le32 module_vendor; __le32 date; /* BCD YYYMMDD */ - __le32 size; /* in dwords */ + __le32 size; __le32 key_size; /* in dwords */ __le32 modulus_size; /* in dwords */ __le32 exponent_size; /* in dwords */ @@ -168,6 +168,16 @@ enum i2400m_brh { }; +/* Constants for bcf->module_id */ +enum i2400m_bcf_mod_id { + /* Firmware file carries its own pokes -- pokes are a set of + * magical values that have to be written in certain memory + * addresses to get the device up and ready for firmware + * download when it is in non-signed boot mode. */ + I2400M_BCF_MOD_ID_POKES = 0x000000001, +}; + + /** * i2400m_bootrom_header - Header for a boot-mode command * @@ -266,7 +276,6 @@ enum { I2400M_WARM_RESET_BARKER = 0x50f750f7, I2400M_NBOOT_BARKER = 0xdeadbeef, I2400M_SBOOT_BARKER = 0x0ff1c1a1, - I2400M_SBOOT_BARKER_6050 = 0x80000001, I2400M_ACK_BARKER = 0xfeedbabe, I2400M_D2H_MSG_BARKER = 0xbeefbabe, }; diff --git a/trunk/include/net/ieee80211_radiotap.h b/trunk/include/net/ieee80211_radiotap.h index 9d3d86aaccbb..23c3f3d97779 100644 --- a/trunk/include/net/ieee80211_radiotap.h +++ b/trunk/include/net/ieee80211_radiotap.h @@ -80,7 +80,7 @@ struct ieee80211_radiotap_header { * Additional extensions are made * by setting bit 31. */ -} __packed; +}; /* Name Data type Units * ---- --------- ----- diff --git a/trunk/include/net/inet_hashtables.h b/trunk/include/net/inet_hashtables.h index 41cbddd25b70..5b698b3b463d 100644 --- a/trunk/include/net/inet_hashtables.h +++ b/trunk/include/net/inet_hashtables.h @@ -92,8 +92,8 @@ static inline struct net *ib_net(struct inet_bind_bucket *ib) return read_pnet(&ib->ib_net); } -#define inet_bind_bucket_for_each(tb, pos, head) \ - hlist_for_each_entry(tb, pos, head, node) +#define inet_bind_bucket_for_each(tb, node, head) \ + hlist_for_each_entry(tb, node, head, node) struct inet_bind_hashbucket { spinlock_t lock; diff --git a/trunk/include/net/inetpeer.h b/trunk/include/net/inetpeer.h index 87b1df0d4d8c..35ad7b930467 100644 --- a/trunk/include/net/inetpeer.h +++ b/trunk/include/net/inetpeer.h @@ -17,15 +17,15 @@ struct inet_peer { /* group together avl_left,avl_right,v4daddr to speedup lookups */ struct inet_peer *avl_left, *avl_right; __be32 v4daddr; /* peer's address */ - __u32 avl_height; + __u16 avl_height; + __u16 ip_id_count; /* IP ID for the next packet */ struct list_head unused; __u32 dtime; /* the time of last use of not * referenced entries */ atomic_t refcnt; atomic_t rid; /* Frag reception counter */ - atomic_t ip_id_count; /* IP ID for the next packet */ __u32 tcp_ts; - __u32 tcp_ts_stamp; + unsigned long tcp_ts_stamp; }; void inet_initpeers(void) __init; @@ -36,11 +36,17 @@ struct inet_peer *inet_getpeer(__be32 daddr, int create); /* can be called from BH context or outside */ extern void inet_putpeer(struct inet_peer *p); +extern spinlock_t inet_peer_idlock; /* can be called with or without local BH being disabled */ static inline __u16 inet_getid(struct inet_peer *p, int more) { - more++; - return atomic_add_return(more, &p->ip_id_count) - more; + __u16 id; + + spin_lock_bh(&inet_peer_idlock); + id = p->ip_id_count; + p->ip_id_count += 1 + more; + spin_unlock_bh(&inet_peer_idlock); + return id; } #endif /* _NET_INETPEER_H */ diff --git a/trunk/include/net/ip_fib.h b/trunk/include/net/ip_fib.h index c93f94edc610..68fd5ebd0949 100644 --- a/trunk/include/net/ip_fib.h +++ b/trunk/include/net/ip_fib.h @@ -213,8 +213,7 @@ extern struct fib_table *fib_get_table(struct net *net, u32 id); extern const struct nla_policy rtm_ipv4_policy[]; extern void ip_fib_init(void); extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, - struct net_device *dev, __be32 *spec_dst, - u32 *itag, u32 mark); + struct net_device *dev, __be32 *spec_dst, u32 *itag); extern void fib_select_default(struct net *net, const struct flowi *flp, struct fib_result *res); diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h index 2c10eac637d8..c42c4a820b89 100644 --- a/trunk/include/net/mac80211.h +++ b/trunk/include/net/mac80211.h @@ -494,6 +494,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * @RX_FLAG_MMIC_ERROR: Michael MIC error was reported on this frame. * Use together with %RX_FLAG_MMIC_STRIPPED. * @RX_FLAG_DECRYPTED: This frame was decrypted in hardware. + * @RX_FLAG_RADIOTAP: This frame starts with a radiotap header. * @RX_FLAG_MMIC_STRIPPED: the Michael MIC is stripped off this frame, * verification has been done by the hardware. * @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame. @@ -514,6 +515,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) enum mac80211_rx_flags { RX_FLAG_MMIC_ERROR = 1<<0, RX_FLAG_DECRYPTED = 1<<1, + RX_FLAG_RADIOTAP = 1<<2, RX_FLAG_MMIC_STRIPPED = 1<<3, RX_FLAG_IV_STRIPPED = 1<<4, RX_FLAG_FAILED_FCS_CRC = 1<<5, @@ -552,7 +554,7 @@ struct ieee80211_rx_status { int freq; int signal; int noise; - int __deprecated qual; + int qual; int antenna; int rate_idx; int flag; @@ -563,9 +565,7 @@ struct ieee80211_rx_status { * * Flags to define PHY configuration options * - * @IEEE80211_CONF_MONITOR: there's a monitor interface present -- use this - * to determine for example whether to calculate timestamps for packets - * or not, do not use instead of filter flags! + * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported) * @IEEE80211_CONF_PS: Enable 802.11 power save mode (managed mode only) * @IEEE80211_CONF_IDLE: The device is running, but idle; if the flag is set * the driver should be prepared to handle configuration requests but @@ -574,7 +574,7 @@ struct ieee80211_rx_status { * it can also be unset in that case when monitor interfaces are active. */ enum ieee80211_conf_flags { - IEEE80211_CONF_MONITOR = (1<<0), + IEEE80211_CONF_RADIOTAP = (1<<0), IEEE80211_CONF_PS = (1<<1), IEEE80211_CONF_IDLE = (1<<2), }; @@ -584,7 +584,7 @@ enum ieee80211_conf_flags { * enum ieee80211_conf_changed - denotes which configuration changed * * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed - * @IEEE80211_CONF_CHANGE_MONITOR: the monitor flag changed + * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed * @IEEE80211_CONF_CHANGE_PS: the PS flag or dynamic PS timeout changed * @IEEE80211_CONF_CHANGE_POWER: the TX power changed * @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed @@ -593,7 +593,7 @@ enum ieee80211_conf_flags { */ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), - IEEE80211_CONF_CHANGE_MONITOR = BIT(3), + IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3), IEEE80211_CONF_CHANGE_PS = BIT(4), IEEE80211_CONF_CHANGE_POWER = BIT(5), IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), @@ -1661,7 +1661,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw); * ieee80211_rx - receive frame * * Use this function to hand received frames to mac80211. The receive - * buffer in @skb must start with an IEEE 802.11 header. + * buffer in @skb must start with an IEEE 802.11 header or a radiotap + * header if %RX_FLAG_RADIOTAP is set in the @status flags. * * This function may not be called in IRQ context. Calls to this function * for a single hardware must be synchronized against each other. Calls to @@ -1742,46 +1743,20 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb); -/** - * ieee80211_beacon_get_tim - beacon generation function - * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. - * @tim_offset: pointer to variable that will receive the TIM IE offset. - * Set to 0 if invalid (in non-AP modes). - * @tim_length: pointer to variable that will receive the TIM IE length, - * (including the ID and length bytes!). - * Set to 0 if invalid (in non-AP modes). - * - * If the driver implements beaconing modes, it must use this function to - * obtain the beacon frame/template. - * - * If the beacon frames are generated by the host system (i.e., not in - * hardware/firmware), the driver uses this function to get each beacon - * frame from mac80211 -- it is responsible for calling this function - * before the beacon is needed (e.g. based on hardware interrupt). - * - * If the beacon frames are generated by the device, then the driver - * must use the returned beacon as the template and change the TIM IE - * according to the current DTIM parameters/TIM bitmap. - * - * The driver is responsible for freeing the returned skb. - */ -struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - u16 *tim_offset, u16 *tim_length); - /** * ieee80211_beacon_get - beacon generation function * @hw: pointer obtained from ieee80211_alloc_hw(). * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. * - * See ieee80211_beacon_get_tim(). + * If the beacon frames are generated by the host system (i.e., not in + * hardware/firmware), the low-level driver uses this function to receive + * the next beacon frame from the 802.11 code. The low-level is responsible + * for calling this function before beacon data is needed (e.g., based on + * hardware interrupt). Returned skb is used only once and low-level driver + * is responsible for freeing it. */ -static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - return ieee80211_beacon_get_tim(hw, vif, NULL, NULL); -} +struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); /** * ieee80211_rts_get - RTS frame generation function @@ -2106,68 +2081,15 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, /** * ieee80211_find_sta - find a station * - * @vif: virtual interface to look for station on + * @hw: pointer as obtained from ieee80211_alloc_hw() * @addr: station's address * * This function must be called under RCU lock and the * resulting pointer is only valid under RCU lock as well. */ -struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, +struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, const u8 *addr); -/** - * ieee80211_find_sta_by_hw - find a station on hardware - * - * @hw: pointer as obtained from ieee80211_alloc_hw() - * @addr: station's address - * - * This function must be called under RCU lock and the - * resulting pointer is only valid under RCU lock as well. - * - * NOTE: This function should not be used! When mac80211 is converted - * internally to properly keep track of stations on multiple - * virtual interfaces, it will not always know which station to - * return here since a single address might be used by multiple - * logical stations (e.g. consider a station connecting to another - * BSSID on the same AP hardware without disconnecting first). - * - * DO NOT USE THIS FUNCTION. - */ -struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, - const u8 *addr); - -/** - * ieee80211_sta_block_awake - block station from waking up - * @hw: the hardware - * @pubsta: the station - * @block: whether to block or unblock - * - * Some devices require that all frames that are on the queues - * for a specific station that went to sleep are flushed before - * a poll response or frames after the station woke up can be - * delivered to that it. Note that such frames must be rejected - * by the driver as filtered, with the appropriate status flag. - * - * This function allows implementing this mode in a race-free - * manner. - * - * To do this, a driver must keep track of the number of frames - * still enqueued for a specific station. If this number is not - * zero when the station goes to sleep, the driver must call - * this function to force mac80211 to consider the station to - * be asleep regardless of the station's actual state. Once the - * number of outstanding frames reaches zero, the driver must - * call this function again to unblock the station. That will - * cause mac80211 to be able to send ps-poll responses, and if - * the station queried in the meantime then frames will also - * be sent out as a result of this. Additionally, the driver - * will be notified that the station woke up some time after - * it is unblocked, regardless of whether the station actually - * woke up while blocked or not. - */ -void ieee80211_sta_block_awake(struct ieee80211_hw *hw, - struct ieee80211_sta *pubsta, bool block); - /** * ieee80211_beacon_loss - inform hardware does not receive beacons * diff --git a/trunk/include/net/netfilter/nf_conntrack.h b/trunk/include/net/netfilter/nf_conntrack.h index 5cf7270e3ffc..cbdd6284996d 100644 --- a/trunk/include/net/netfilter/nf_conntrack.h +++ b/trunk/include/net/netfilter/nf_conntrack.h @@ -255,9 +255,11 @@ static inline bool nf_ct_kill(struct nf_conn *ct) } /* These are for NAT. Icky. */ -extern s16 (*nf_ct_nat_offset)(const struct nf_conn *ct, - enum ip_conntrack_dir dir, - u32 seq); +/* Update TCP window tracking data when NAT mangles the packet */ +extern void nf_conntrack_tcp_update(const struct sk_buff *skb, + unsigned int dataoff, + struct nf_conn *ct, int dir, + s16 offset); /* Fake conntrack entry for untracked connections */ extern struct nf_conn nf_conntrack_untracked; diff --git a/trunk/include/net/netfilter/nf_nat_helper.h b/trunk/include/net/netfilter/nf_nat_helper.h index 4222220920a5..237a961f40e1 100644 --- a/trunk/include/net/netfilter/nf_nat_helper.h +++ b/trunk/include/net/netfilter/nf_nat_helper.h @@ -32,8 +32,4 @@ extern int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb, * to port ct->master->saved_proto. */ extern void nf_nat_follow_master(struct nf_conn *ct, struct nf_conntrack_expect *this); - -extern s16 nf_nat_get_offset(const struct nf_conn *ct, - enum ip_conntrack_dir dir, - u32 seq); #endif diff --git a/trunk/include/net/phonet/phonet.h b/trunk/include/net/phonet/phonet.h index 7b114079a51b..fdb05fa0346f 100644 --- a/trunk/include/net/phonet/phonet.h +++ b/trunk/include/net/phonet/phonet.h @@ -46,7 +46,6 @@ static inline struct pn_sock *pn_sk(struct sock *sk) extern const struct proto_ops phonet_dgram_ops; -void pn_sock_init(void); struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *sa); void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb); void phonet_get_local_port_range(int *min, int *max); diff --git a/trunk/include/net/protocol.h b/trunk/include/net/protocol.h index f1effdd3c265..89932d45da59 100644 --- a/trunk/include/net/protocol.h +++ b/trunk/include/net/protocol.h @@ -82,6 +82,10 @@ struct inet_protosw { struct proto *prot; const struct proto_ops *ops; + int capability; /* Which (if any) capability do + * we need to use this socket + * interface? + */ char no_check; /* checksum on rcv/xmit/none? */ unsigned char flags; /* See INET_PROTOSW_* below. */ }; diff --git a/trunk/include/net/rtnetlink.h b/trunk/include/net/rtnetlink.h index 48d3efcb0880..cd5af1f508f2 100644 --- a/trunk/include/net/rtnetlink.h +++ b/trunk/include/net/rtnetlink.h @@ -55,8 +55,7 @@ struct rtnl_link_ops { int (*validate)(struct nlattr *tb[], struct nlattr *data[]); - int (*newlink)(struct net *src_net, - struct net_device *dev, + int (*newlink)(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]); int (*changelink)(struct net_device *dev, @@ -84,9 +83,8 @@ extern void rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops); extern int rtnl_link_register(struct rtnl_link_ops *ops); extern void rtnl_link_unregister(struct rtnl_link_ops *ops); -extern struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]); -extern struct net_device *rtnl_create_link(struct net *src_net, struct net *net, - char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]); +extern struct net_device *rtnl_create_link(struct net *net, char *ifname, + const struct rtnl_link_ops *ops, struct nlattr *tb[]); extern const struct nla_policy ifla_policy[IFLA_MAX+1]; #define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind) diff --git a/trunk/include/net/sock.h b/trunk/include/net/sock.h index 3f1a4804bb3f..55de3bd719a5 100644 --- a/trunk/include/net/sock.h +++ b/trunk/include/net/sock.h @@ -105,17 +105,15 @@ struct net; /** * struct sock_common - minimal network layer representation of sockets * @skc_node: main hash linkage for various protocol lookup tables - * @skc_nulls_node: main hash linkage for TCP/UDP/UDP-Lite protocol + * @skc_nulls_node: main hash linkage for UDP/UDP-Lite protocol * @skc_refcnt: reference count * @skc_tx_queue_mapping: tx queue number for this connection * @skc_hash: hash value used with various protocol lookup tables - * @skc_u16hashes: two u16 hash values used by UDP lookup tables * @skc_family: network address family * @skc_state: Connection state * @skc_reuse: %SO_REUSEADDR setting * @skc_bound_dev_if: bound device index if != 0 * @skc_bind_node: bind hash linkage for various protocol lookup tables - * @skc_portaddr_node: second hash linkage for UDP/UDP-Lite protocol * @skc_prot: protocol handlers inside a network family * @skc_net: reference to the network namespace of this socket * @@ -133,18 +131,12 @@ struct sock_common { atomic_t skc_refcnt; int skc_tx_queue_mapping; - union { - unsigned int skc_hash; - __u16 skc_u16hashes[2]; - }; + unsigned int skc_hash; unsigned short skc_family; volatile unsigned char skc_state; unsigned char skc_reuse; int skc_bound_dev_if; - union { - struct hlist_node skc_bind_node; - struct hlist_nulls_node skc_portaddr_node; - }; + struct hlist_node skc_bind_node; struct proto *skc_prot; #ifdef CONFIG_NET_NS struct net *skc_net; diff --git a/trunk/include/net/tcp.h b/trunk/include/net/tcp.h index 325bfcf5c934..bf20f88fd033 100644 --- a/trunk/include/net/tcp.h +++ b/trunk/include/net/tcp.h @@ -62,6 +62,9 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); /* Minimal accepted MSS. It is (60+60+8) - (20+20). */ #define TCP_MIN_MSS 88U +/* Minimal RCV_MSS. */ +#define TCP_MIN_RCVMSS 536U + /* The least MTU to use for probing */ #define TCP_BASE_MSS 512 diff --git a/trunk/include/net/udp.h b/trunk/include/net/udp.h index 5348d80b25bb..22aa2e7eb1d7 100644 --- a/trunk/include/net/udp.h +++ b/trunk/include/net/udp.h @@ -50,32 +50,15 @@ struct udp_skb_cb { }; #define UDP_SKB_CB(__skb) ((struct udp_skb_cb *)((__skb)->cb)) -/** - * struct udp_hslot - UDP hash slot - * - * @head: head of list of sockets - * @count: number of sockets in 'head' list - * @lock: spinlock protecting changes to head/count - */ struct udp_hslot { struct hlist_nulls_head head; - int count; spinlock_t lock; } __attribute__((aligned(2 * sizeof(long)))); -/** - * struct udp_table - UDP table - * - * @hash: hash table, sockets are hashed on (local port) - * @hash2: hash table, sockets are hashed on (local port, local address) - * @mask: number of slots in hash tables, minus 1 - * @log: log2(number of slots in hash table) - */ struct udp_table { struct udp_hslot *hash; - struct udp_hslot *hash2; - unsigned int mask; - unsigned int log; + unsigned int mask; + unsigned int log; }; extern struct udp_table udp_table; extern void udp_table_init(struct udp_table *, const char *); @@ -84,15 +67,6 @@ static inline struct udp_hslot *udp_hashslot(struct udp_table *table, { return &table->hash[udp_hashfn(net, num, table->mask)]; } -/* - * For secondary hash, net_hash_mix() is performed before calling - * udp_hashslot2(), this explains difference with udp_hashslot() - */ -static inline struct udp_hslot *udp_hashslot2(struct udp_table *table, - unsigned int hash) -{ - return &table->hash2[hash & table->mask]; -} /* Note: this must match 'valbool' in sock_setsockopt */ #define UDP_CSUM_NOXMIT 1 @@ -158,8 +132,7 @@ static inline void udp_lib_close(struct sock *sk, long timeout) } extern int udp_lib_get_port(struct sock *sk, unsigned short snum, - int (*)(const struct sock *,const struct sock *), - unsigned int hash2_nulladdr); + int (*)(const struct sock*,const struct sock*)); /* net/ipv4/udp.c */ extern int udp_get_port(struct sock *sk, unsigned short snum, diff --git a/trunk/include/net/wimax.h b/trunk/include/net/wimax.h index d69c4a7a1267..2af7bf839f23 100644 --- a/trunk/include/net/wimax.h +++ b/trunk/include/net/wimax.h @@ -195,12 +195,6 @@ * defining the `struct nla_policy` for each message, it has to have * an array size of WIMAX_GNL_ATTR_MAX+1. * - * The op_*() function pointers will not be called if the wimax_dev is - * in a state <= %WIMAX_ST_UNINITIALIZED. The exception is: - * - * - op_reset: can be called at any time after wimax_dev_add() has - * been called. - * * THE PIPE INTERFACE: * * This interface is kept intentionally simple. The driver can send diff --git a/trunk/include/net/xfrm.h b/trunk/include/net/xfrm.h index 93d184b91a8c..7f38ef509957 100644 --- a/trunk/include/net/xfrm.h +++ b/trunk/include/net/xfrm.h @@ -19,9 +19,6 @@ #include #include #include - -#include - #ifdef CONFIG_XFRM_STATISTICS #include #endif @@ -201,7 +198,7 @@ struct xfrm_state { struct xfrm_stats stats; struct xfrm_lifetime_cur curlft; - struct tasklet_hrtimer mtimer; + struct timer_list timer; /* Last used time */ unsigned long lastused; diff --git a/trunk/kernel/time/clocksource.c b/trunk/kernel/time/clocksource.c index 4a310906b3e8..5e18c6ab2c6a 100644 --- a/trunk/kernel/time/clocksource.c +++ b/trunk/kernel/time/clocksource.c @@ -39,7 +39,7 @@ void timecounter_init(struct timecounter *tc, tc->cycle_last = cc->read(cc); tc->nsec = start_tstamp; } -EXPORT_SYMBOL_GPL(timecounter_init); +EXPORT_SYMBOL(timecounter_init); /** * timecounter_read_delta - get nanoseconds since last call of this function @@ -83,7 +83,7 @@ u64 timecounter_read(struct timecounter *tc) return nsec; } -EXPORT_SYMBOL_GPL(timecounter_read); +EXPORT_SYMBOL(timecounter_read); u64 timecounter_cyc2time(struct timecounter *tc, cycle_t cycle_tstamp) @@ -105,7 +105,7 @@ u64 timecounter_cyc2time(struct timecounter *tc, return nsec; } -EXPORT_SYMBOL_GPL(timecounter_cyc2time); +EXPORT_SYMBOL(timecounter_cyc2time); /*[Clocksource internal variables]--------- * curr_clocksource: diff --git a/trunk/kernel/time/timecompare.c b/trunk/kernel/time/timecompare.c index 96ff643a5a59..71e7f1a19156 100644 --- a/trunk/kernel/time/timecompare.c +++ b/trunk/kernel/time/timecompare.c @@ -40,7 +40,7 @@ ktime_t timecompare_transform(struct timecompare *sync, return ns_to_ktime(nsec); } -EXPORT_SYMBOL_GPL(timecompare_transform); +EXPORT_SYMBOL(timecompare_transform); int timecompare_offset(struct timecompare *sync, s64 *offset, @@ -131,7 +131,7 @@ int timecompare_offset(struct timecompare *sync, return used; } -EXPORT_SYMBOL_GPL(timecompare_offset); +EXPORT_SYMBOL(timecompare_offset); void __timecompare_update(struct timecompare *sync, u64 source_tstamp) @@ -188,4 +188,4 @@ void __timecompare_update(struct timecompare *sync, } } } -EXPORT_SYMBOL_GPL(__timecompare_update); +EXPORT_SYMBOL(__timecompare_update); diff --git a/trunk/net/8021q/vlan_dev.c b/trunk/net/8021q/vlan_dev.c index 915965942139..790fd55ec318 100644 --- a/trunk/net/8021q/vlan_dev.c +++ b/trunk/net/8021q/vlan_dev.c @@ -332,7 +332,7 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, } else txq->tx_dropped++; - return ret; + return NETDEV_TX_OK; } static netdev_tx_t vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, @@ -358,7 +358,7 @@ static netdev_tx_t vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, } else txq->tx_dropped++; - return ret; + return NETDEV_TX_OK; } static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) diff --git a/trunk/net/8021q/vlan_netlink.c b/trunk/net/8021q/vlan_netlink.c index 3c9cf6a8e7fb..a91504850195 100644 --- a/trunk/net/8021q/vlan_netlink.c +++ b/trunk/net/8021q/vlan_netlink.c @@ -119,7 +119,7 @@ static int vlan_get_tx_queues(struct net *net, return 0; } -static int vlan_newlink(struct net *src_net, struct net_device *dev, +static int vlan_newlink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { struct vlan_dev_info *vlan = vlan_dev_info(dev); @@ -131,7 +131,7 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev, if (!tb[IFLA_LINK]) return -EINVAL; - real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); + real_dev = __dev_get_by_index(dev_net(dev), nla_get_u32(tb[IFLA_LINK])); if (!real_dev) return -ENODEV; diff --git a/trunk/net/8021q/vlanproc.c b/trunk/net/8021q/vlanproc.c index 9ec1f057c03a..6262c335f3c2 100644 --- a/trunk/net/8021q/vlanproc.c +++ b/trunk/net/8021q/vlanproc.c @@ -201,17 +201,18 @@ int vlan_proc_rem_dev(struct net_device *vlandev) /* start read of /proc/net/vlan/config */ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(rcu) + __acquires(dev_base_lock) { struct net_device *dev; struct net *net = seq_file_net(seq); loff_t i = 1; - rcu_read_lock(); + read_lock(&dev_base_lock); + if (*pos == 0) return SEQ_START_TOKEN; - for_each_netdev_rcu(net, dev) { + for_each_netdev(net, dev) { if (!is_vlan_dev(dev)) continue; @@ -233,7 +234,7 @@ static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos) if (v == SEQ_START_TOKEN) dev = net_device_entry(&net->dev_base_head); - for_each_netdev_continue_rcu(net, dev) { + for_each_netdev_continue(net, dev) { if (!is_vlan_dev(dev)) continue; @@ -244,9 +245,9 @@ static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void vlan_seq_stop(struct seq_file *seq, void *v) - __releases(rcu) + __releases(dev_base_lock) { - rcu_read_unlock(); + read_unlock(&dev_base_lock); } static int vlan_seq_show(struct seq_file *seq, void *v) diff --git a/trunk/net/appletalk/ddp.c b/trunk/net/appletalk/ddp.c index 73ca4d524928..abe38014b7fd 100644 --- a/trunk/net/appletalk/ddp.c +++ b/trunk/net/appletalk/ddp.c @@ -56,7 +56,6 @@ #include #include #include /* For TIOCOUTQ/INQ */ -#include #include #include #include @@ -923,8 +922,13 @@ static unsigned long atalk_sum_partial(const unsigned char *data, { /* This ought to be unwrapped neatly. I'll trust gcc for now */ while (len--) { - sum += *data++; - sum = rol16(sum, 1); + sum += *data; + sum <<= 1; + if (sum & 0x10000) { + sum++; + sum &= 0xffff; + } + data++; } return sum; } @@ -1017,8 +1021,7 @@ static struct proto ddp_proto = { * Create a socket. Initialise the socket, blank the addresses * set the state. */ -static int atalk_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int atalk_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; int rc = -ESOCKTNOSUPPORT; @@ -1051,13 +1054,11 @@ static int atalk_release(struct socket *sock) { struct sock *sk = sock->sk; - lock_kernel(); if (sk) { sock_orphan(sk); sock->sk = NULL; atalk_destroy_socket(sk); } - unlock_kernel(); return 0; } @@ -1133,7 +1134,6 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct sockaddr_at *addr = (struct sockaddr_at *)uaddr; struct sock *sk = sock->sk; struct atalk_sock *at = at_sk(sk); - int err; if (!sock_flag(sk, SOCK_ZAPPED) || addr_len != sizeof(struct sockaddr_at)) @@ -1142,44 +1142,37 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (addr->sat_family != AF_APPLETALK) return -EAFNOSUPPORT; - lock_kernel(); if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) { struct atalk_addr *ap = atalk_find_primary(); - err = -EADDRNOTAVAIL; if (!ap) - goto out; + return -EADDRNOTAVAIL; at->src_net = addr->sat_addr.s_net = ap->s_net; at->src_node = addr->sat_addr.s_node= ap->s_node; } else { - err = -EADDRNOTAVAIL; if (!atalk_find_interface(addr->sat_addr.s_net, addr->sat_addr.s_node)) - goto out; + return -EADDRNOTAVAIL; at->src_net = addr->sat_addr.s_net; at->src_node = addr->sat_addr.s_node; } if (addr->sat_port == ATADDR_ANYPORT) { - err = atalk_pick_and_bind_port(sk, addr); + int n = atalk_pick_and_bind_port(sk, addr); - if (err < 0) - goto out; + if (n < 0) + return n; } else { at->src_port = addr->sat_port; - err = -EADDRINUSE; if (atalk_find_or_insert_socket(sk, addr)) - goto out; + return -EADDRINUSE; } sock_reset_flag(sk, SOCK_ZAPPED); - err = 0; -out: - unlock_kernel(); - return err; + return 0; } /* Set the address we talk to */ @@ -1189,7 +1182,6 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, struct sock *sk = sock->sk; struct atalk_sock *at = at_sk(sk); struct sockaddr_at *addr; - int err; sk->sk_state = TCP_CLOSE; sock->state = SS_UNCONNECTED; @@ -1214,15 +1206,12 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, #endif } - lock_kernel(); - err = -EBUSY; if (sock_flag(sk, SOCK_ZAPPED)) if (atalk_autobind(sk) < 0) - goto out; + return -EBUSY; - err = -ENETUNREACH; if (!atrtr_get_dev(&addr->sat_addr)) - goto out; + return -ENETUNREACH; at->dest_port = addr->sat_port; at->dest_net = addr->sat_addr.s_net; @@ -1230,10 +1219,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, sock->state = SS_CONNECTED; sk->sk_state = TCP_ESTABLISHED; - err = 0; -out: - unlock_kernel(); - return err; + return 0; } /* @@ -1246,21 +1232,17 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, struct sockaddr_at sat; struct sock *sk = sock->sk; struct atalk_sock *at = at_sk(sk); - int err; - lock_kernel(); - err = -ENOBUFS; if (sock_flag(sk, SOCK_ZAPPED)) if (atalk_autobind(sk) < 0) - goto out; + return -ENOBUFS; *uaddr_len = sizeof(struct sockaddr_at); memset(&sat.sat_zero, 0, sizeof(sat.sat_zero)); if (peer) { - err = -ENOTCONN; if (sk->sk_state != TCP_ESTABLISHED) - goto out; + return -ENOTCONN; sat.sat_addr.s_net = at->dest_net; sat.sat_addr.s_node = at->dest_node; @@ -1271,23 +1253,9 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, sat.sat_port = at->src_port; } - err = 0; sat.sat_family = AF_APPLETALK; memcpy(uaddr, &sat, sizeof(sat)); - -out: - unlock_kernel(); - return err; -} - -static unsigned int atalk_poll(struct file *file, struct socket *sock, - poll_table *wait) -{ - int err; - lock_kernel(); - err = datagram_poll(file, sock, wait); - unlock_kernel(); - return err; + return 0; } #if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE) @@ -1595,28 +1563,23 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr if (len > DDP_MAXSZ) return -EMSGSIZE; - lock_kernel(); if (usat) { - err = -EBUSY; if (sock_flag(sk, SOCK_ZAPPED)) if (atalk_autobind(sk) < 0) - goto out; + return -EBUSY; - err = -EINVAL; if (msg->msg_namelen < sizeof(*usat) || usat->sat_family != AF_APPLETALK) - goto out; + return -EINVAL; - err = -EPERM; /* netatalk didn't implement this check */ if (usat->sat_addr.s_node == ATADDR_BCAST && !sock_flag(sk, SOCK_BROADCAST)) { - goto out; + return -EPERM; } } else { - err = -ENOTCONN; if (sk->sk_state != TCP_ESTABLISHED) - goto out; + return -ENOTCONN; usat = &local_satalk; usat->sat_family = AF_APPLETALK; usat->sat_port = at->dest_port; @@ -1640,9 +1603,8 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr rt = atrtr_find(&at_hint); } - err = ENETUNREACH; if (!rt) - goto out; + return -ENETUNREACH; dev = rt->dev; @@ -1652,7 +1614,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr size += dev->hard_header_len; skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err); if (!skb) - goto out; + return err; skb->sk = sk; skb_reserve(skb, ddp_dl->header_length); @@ -1675,8 +1637,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); if (err) { kfree_skb(skb); - err = -EFAULT; - goto out; + return -EFAULT; } if (sk->sk_no_check == 1) @@ -1715,8 +1676,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr rt = atrtr_find(&at_lo); if (!rt) { kfree_skb(skb); - err = -ENETUNREACH; - goto out; + return -ENETUNREACH; } dev = rt->dev; skb->dev = dev; @@ -1736,9 +1696,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr } SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len); -out: - unlock_kernel(); - return err ? : len; + return len; } static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, @@ -1750,13 +1708,10 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr int copied = 0; int offset = 0; int err = 0; - struct sk_buff *skb; - - lock_kernel(); - skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, + struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &err); if (!skb) - goto out; + return err; /* FIXME: use skb->cb to be able to use shared skbs */ ddp = ddp_hdr(skb); @@ -1784,9 +1739,6 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr } skb_free_datagram(sk, skb); /* Free the datagram. */ - -out: - unlock_kernel(); return err ? : copied; } @@ -1858,14 +1810,12 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) static int atalk_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { /* - * SIOCATALKDIFADDR is a SIOCPROTOPRIVATE ioctl number, so we - * cannot handle it in common code. The data we access if ifreq - * here is compatible, so we can simply call the native - * handler. + * All Appletalk ioctls except SIOCATALKDIFADDR are standard. And + * SIOCATALKDIFADDR is handled by upper layer as well, so there is + * nothing to do. Eventually SIOCATALKDIFADDR should be moved + * here so there is no generic SIOCPROTOPRIVATE translation in the + * system. */ - if (cmd == SIOCATALKDIFADDR) - return atalk_ioctl(sock, cmd, (unsigned long)compat_ptr(arg)); - return -ENOIOCTLCMD; } #endif @@ -1877,7 +1827,7 @@ static const struct net_proto_family atalk_family_ops = { .owner = THIS_MODULE, }; -static const struct proto_ops atalk_dgram_ops = { +static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { .family = PF_APPLETALK, .owner = THIS_MODULE, .release = atalk_release, @@ -1886,7 +1836,7 @@ static const struct proto_ops atalk_dgram_ops = { .socketpair = sock_no_socketpair, .accept = sock_no_accept, .getname = atalk_getname, - .poll = atalk_poll, + .poll = datagram_poll, .ioctl = atalk_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = atalk_compat_ioctl, @@ -1901,6 +1851,8 @@ static const struct proto_ops atalk_dgram_ops = { .sendpage = sock_no_sendpage, }; +SOCKOPS_WRAP(atalk_dgram, PF_APPLETALK); + static struct notifier_block ddp_notifier = { .notifier_call = ddp_device_event, }; diff --git a/trunk/net/atm/ioctl.c b/trunk/net/atm/ioctl.c index 2ea40995dced..4da8892ced5f 100644 --- a/trunk/net/atm/ioctl.c +++ b/trunk/net/atm/ioctl.c @@ -191,181 +191,8 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) } #ifdef CONFIG_COMPAT -/* - * FIXME: - * The compat_ioctl handling is duplicated, using both these conversion - * routines and the compat argument to the actual handlers. Both - * versions are somewhat incomplete and should be merged, e.g. by - * moving the ioctl number translation into the actual handlers and - * killing the conversion code. - * - * -arnd, November 2009 - */ -#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct compat_atmif_sioc) -#define ATM_GETNAMES32 _IOW('a', ATMIOC_ITF+3, struct compat_atm_iobuf) -#define ATM_GETTYPE32 _IOW('a', ATMIOC_ITF+4, struct compat_atmif_sioc) -#define ATM_GETESI32 _IOW('a', ATMIOC_ITF+5, struct compat_atmif_sioc) -#define ATM_GETADDR32 _IOW('a', ATMIOC_ITF+6, struct compat_atmif_sioc) -#define ATM_RSTADDR32 _IOW('a', ATMIOC_ITF+7, struct compat_atmif_sioc) -#define ATM_ADDADDR32 _IOW('a', ATMIOC_ITF+8, struct compat_atmif_sioc) -#define ATM_DELADDR32 _IOW('a', ATMIOC_ITF+9, struct compat_atmif_sioc) -#define ATM_GETCIRANGE32 _IOW('a', ATMIOC_ITF+10, struct compat_atmif_sioc) -#define ATM_SETCIRANGE32 _IOW('a', ATMIOC_ITF+11, struct compat_atmif_sioc) -#define ATM_SETESI32 _IOW('a', ATMIOC_ITF+12, struct compat_atmif_sioc) -#define ATM_SETESIF32 _IOW('a', ATMIOC_ITF+13, struct compat_atmif_sioc) -#define ATM_GETSTAT32 _IOW('a', ATMIOC_SARCOM+0, struct compat_atmif_sioc) -#define ATM_GETSTATZ32 _IOW('a', ATMIOC_SARCOM+1, struct compat_atmif_sioc) -#define ATM_GETLOOP32 _IOW('a', ATMIOC_SARCOM+2, struct compat_atmif_sioc) -#define ATM_SETLOOP32 _IOW('a', ATMIOC_SARCOM+3, struct compat_atmif_sioc) -#define ATM_QUERYLOOP32 _IOW('a', ATMIOC_SARCOM+4, struct compat_atmif_sioc) - -static struct { - unsigned int cmd32; - unsigned int cmd; -} atm_ioctl_map[] = { - { ATM_GETLINKRATE32, ATM_GETLINKRATE }, - { ATM_GETNAMES32, ATM_GETNAMES }, - { ATM_GETTYPE32, ATM_GETTYPE }, - { ATM_GETESI32, ATM_GETESI }, - { ATM_GETADDR32, ATM_GETADDR }, - { ATM_RSTADDR32, ATM_RSTADDR }, - { ATM_ADDADDR32, ATM_ADDADDR }, - { ATM_DELADDR32, ATM_DELADDR }, - { ATM_GETCIRANGE32, ATM_GETCIRANGE }, - { ATM_SETCIRANGE32, ATM_SETCIRANGE }, - { ATM_SETESI32, ATM_SETESI }, - { ATM_SETESIF32, ATM_SETESIF }, - { ATM_GETSTAT32, ATM_GETSTAT }, - { ATM_GETSTATZ32, ATM_GETSTATZ }, - { ATM_GETLOOP32, ATM_GETLOOP }, - { ATM_SETLOOP32, ATM_SETLOOP }, - { ATM_QUERYLOOP32, ATM_QUERYLOOP }, -}; - -#define NR_ATM_IOCTL ARRAY_SIZE(atm_ioctl_map) - -static int do_atm_iobuf(struct socket *sock, unsigned int cmd, - unsigned long arg) -{ - struct atm_iobuf __user *iobuf; - struct compat_atm_iobuf __user *iobuf32; - u32 data; - void __user *datap; - int len, err; - - iobuf = compat_alloc_user_space(sizeof(*iobuf)); - iobuf32 = compat_ptr(arg); - - if (get_user(len, &iobuf32->length) || - get_user(data, &iobuf32->buffer)) - return -EFAULT; - datap = compat_ptr(data); - if (put_user(len, &iobuf->length) || - put_user(datap, &iobuf->buffer)) - return -EFAULT; - - err = do_vcc_ioctl(sock, cmd, (unsigned long) iobuf, 0); - - if (!err) { - if (copy_in_user(&iobuf32->length, &iobuf->length, - sizeof(int))) - err = -EFAULT; - } - - return err; -} - -static int do_atmif_sioc(struct socket *sock, unsigned int cmd, - unsigned long arg) -{ - struct atmif_sioc __user *sioc; - struct compat_atmif_sioc __user *sioc32; - u32 data; - void __user *datap; - int err; - - sioc = compat_alloc_user_space(sizeof(*sioc)); - sioc32 = compat_ptr(arg); - - if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) - || get_user(data, &sioc32->arg)) - return -EFAULT; - datap = compat_ptr(data); - if (put_user(datap, &sioc->arg)) - return -EFAULT; - - err = do_vcc_ioctl(sock, cmd, (unsigned long) sioc, 0); - - if (!err) { - if (copy_in_user(&sioc32->length, &sioc->length, - sizeof(int))) - err = -EFAULT; - } - return err; -} - -static int do_atm_ioctl(struct socket *sock, unsigned int cmd32, - unsigned long arg) -{ - int i; - unsigned int cmd = 0; - - switch (cmd32) { - case SONET_GETSTAT: - case SONET_GETSTATZ: - case SONET_GETDIAG: - case SONET_SETDIAG: - case SONET_CLRDIAG: - case SONET_SETFRAMING: - case SONET_GETFRAMING: - case SONET_GETFRSENSE: - return do_atmif_sioc(sock, cmd32, arg); - } - - for (i = 0; i < NR_ATM_IOCTL; i++) { - if (cmd32 == atm_ioctl_map[i].cmd32) { - cmd = atm_ioctl_map[i].cmd; - break; - } - } - if (i == NR_ATM_IOCTL) - return -EINVAL; - - switch (cmd) { - case ATM_GETNAMES: - return do_atm_iobuf(sock, cmd, arg); - - case ATM_GETLINKRATE: - case ATM_GETTYPE: - case ATM_GETESI: - case ATM_GETADDR: - case ATM_RSTADDR: - case ATM_ADDADDR: - case ATM_DELADDR: - case ATM_GETCIRANGE: - case ATM_SETCIRANGE: - case ATM_SETESI: - case ATM_SETESIF: - case ATM_GETSTAT: - case ATM_GETSTATZ: - case ATM_GETLOOP: - case ATM_SETLOOP: - case ATM_QUERYLOOP: - return do_atmif_sioc(sock, cmd, arg); - } - - return -EINVAL; -} - -int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, - unsigned long arg) +int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { - int ret; - - ret = do_vcc_ioctl(sock, cmd, arg, 1); - if (ret != -ENOIOCTLCMD) - return ret; - - return do_atm_ioctl(sock, cmd, arg); + return do_vcc_ioctl(sock, cmd, arg, 1); } #endif diff --git a/trunk/net/atm/pvc.c b/trunk/net/atm/pvc.c index 8d74e62b0d79..a6e1fdbae87f 100644 --- a/trunk/net/atm/pvc.c +++ b/trunk/net/atm/pvc.c @@ -127,8 +127,7 @@ static const struct proto_ops pvc_proto_ops = { }; -static int pvc_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int pvc_create(struct net *net, struct socket *sock,int protocol) { if (net != &init_net) return -EAFNOSUPPORT; diff --git a/trunk/net/atm/svc.c b/trunk/net/atm/svc.c index c7395070ee78..819354233318 100644 --- a/trunk/net/atm/svc.c +++ b/trunk/net/atm/svc.c @@ -25,7 +25,7 @@ #include "signaling.h" #include "addr.h" -static int svc_create(struct net *net, struct socket *sock, int protocol, int kern); +static int svc_create(struct net *net, struct socket *sock,int protocol); /* * Note: since all this is still nicely synchronized with the signaling demon, @@ -330,7 +330,7 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags) lock_sock(sk); - error = svc_create(sock_net(sk), newsock, 0, 0); + error = svc_create(sock_net(sk), newsock,0); if (error) goto out; @@ -650,8 +650,7 @@ static const struct proto_ops svc_proto_ops = { }; -static int svc_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int svc_create(struct net *net, struct socket *sock,int protocol) { int error; diff --git a/trunk/net/ax25/af_ax25.c b/trunk/net/ax25/af_ax25.c index d6ddfa4c4471..f1e998b2796e 100644 --- a/trunk/net/ax25/af_ax25.c +++ b/trunk/net/ax25/af_ax25.c @@ -799,8 +799,7 @@ static struct proto ax25_proto = { .obj_size = sizeof(struct sock), }; -static int ax25_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int ax25_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; ax25_cb *ax25; diff --git a/trunk/net/bluetooth/af_bluetooth.c b/trunk/net/bluetooth/af_bluetooth.c index 087cc51f5927..399e59c9c6cb 100644 --- a/trunk/net/bluetooth/af_bluetooth.c +++ b/trunk/net/bluetooth/af_bluetooth.c @@ -126,8 +126,7 @@ int bt_sock_unregister(int proto) } EXPORT_SYMBOL(bt_sock_unregister); -static int bt_sock_create(struct net *net, struct socket *sock, int proto, - int kern) +static int bt_sock_create(struct net *net, struct socket *sock, int proto) { int err; @@ -145,7 +144,7 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto, read_lock(&bt_proto_lock); if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { - err = bt_proto[proto]->create(net, sock, proto, kern); + err = bt_proto[proto]->create(net, sock, proto); bt_sock_reclassify_lock(sock, proto); module_put(bt_proto[proto]->owner); } diff --git a/trunk/net/bluetooth/bnep/sock.c b/trunk/net/bluetooth/bnep/sock.c index 2ff6ac7b2ed4..0a2c5460bb48 100644 --- a/trunk/net/bluetooth/bnep/sock.c +++ b/trunk/net/bluetooth/bnep/sock.c @@ -195,8 +195,7 @@ static struct proto bnep_proto = { .obj_size = sizeof(struct bt_sock) }; -static int bnep_sock_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int bnep_sock_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; diff --git a/trunk/net/bluetooth/cmtp/sock.c b/trunk/net/bluetooth/cmtp/sock.c index 978cc3a718ad..de7c8040bc56 100644 --- a/trunk/net/bluetooth/cmtp/sock.c +++ b/trunk/net/bluetooth/cmtp/sock.c @@ -190,8 +190,7 @@ static struct proto cmtp_proto = { .obj_size = sizeof(struct bt_sock) }; -static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; diff --git a/trunk/net/bluetooth/hci_sock.c b/trunk/net/bluetooth/hci_sock.c index 1ca5c7ca9bd4..e7395f231989 100644 --- a/trunk/net/bluetooth/hci_sock.c +++ b/trunk/net/bluetooth/hci_sock.c @@ -621,8 +621,7 @@ static struct proto hci_sk_proto = { .obj_size = sizeof(struct hci_pinfo) }; -static int hci_sock_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int hci_sock_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; diff --git a/trunk/net/bluetooth/hidp/sock.c b/trunk/net/bluetooth/hidp/sock.c index 9cfef68b9fec..4beb6a7a2953 100644 --- a/trunk/net/bluetooth/hidp/sock.c +++ b/trunk/net/bluetooth/hidp/sock.c @@ -241,8 +241,7 @@ static struct proto hidp_proto = { .obj_size = sizeof(struct bt_sock) }; -static int hidp_sock_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int hidp_sock_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; diff --git a/trunk/net/bluetooth/l2cap.c b/trunk/net/bluetooth/l2cap.c index ff0233df6246..d65101d92ee5 100644 --- a/trunk/net/bluetooth/l2cap.c +++ b/trunk/net/bluetooth/l2cap.c @@ -819,8 +819,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p return sk; } -static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; @@ -832,7 +831,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) return -ESOCKTNOSUPPORT; - if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) + if (sock->type == SOCK_RAW && !capable(CAP_NET_RAW)) return -EPERM; sock->ops = &l2cap_sock_ops; diff --git a/trunk/net/bluetooth/rfcomm/sock.c b/trunk/net/bluetooth/rfcomm/sock.c index 4b5968dda673..d3bfc1b0afb1 100644 --- a/trunk/net/bluetooth/rfcomm/sock.c +++ b/trunk/net/bluetooth/rfcomm/sock.c @@ -323,8 +323,7 @@ static struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock, int return sk; } -static int rfcomm_sock_create(struct net *net, struct socket *sock, - int protocol, int kern) +static int rfcomm_sock_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; diff --git a/trunk/net/bluetooth/sco.c b/trunk/net/bluetooth/sco.c index dd8f6ec57dce..694a65541b73 100644 --- a/trunk/net/bluetooth/sco.c +++ b/trunk/net/bluetooth/sco.c @@ -430,8 +430,7 @@ static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int pro return sk; } -static int sco_sock_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int sco_sock_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; diff --git a/trunk/net/bridge/br_if.c b/trunk/net/bridge/br_if.c index a6f74b2b9571..2117e5ba24c8 100644 --- a/trunk/net/bridge/br_if.c +++ b/trunk/net/bridge/br_if.c @@ -377,16 +377,12 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) struct net_bridge_port *p; int err = 0; - /* Don't allow bridging non-ethernet like devices */ - if ((dev->flags & IFF_LOOPBACK) || - dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN) + if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER) return -EINVAL; - /* No bridging of bridges */ if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) return -ELOOP; - /* Device is already being bridged */ if (dev->br_port != NULL) return -EBUSY; diff --git a/trunk/net/bridge/br_ioctl.c b/trunk/net/bridge/br_ioctl.c index 2af6e4a90262..6a6433daaf27 100644 --- a/trunk/net/bridge/br_ioctl.c +++ b/trunk/net/bridge/br_ioctl.c @@ -81,7 +81,6 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf, return num; } -/* called with RTNL */ static int add_del_if(struct net_bridge *br, int ifindex, int isadd) { struct net_device *dev; @@ -90,7 +89,7 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd) if (!capable(CAP_NET_ADMIN)) return -EPERM; - dev = __dev_get_by_index(dev_net(br->dev), ifindex); + dev = dev_get_by_index(dev_net(br->dev), ifindex); if (dev == NULL) return -EINVAL; @@ -99,6 +98,7 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd) else ret = br_del_if(br, dev); + dev_put(dev); return ret; } diff --git a/trunk/net/can/af_can.c b/trunk/net/can/af_can.c index 833bd838edc6..3f2eb27e1ffb 100644 --- a/trunk/net/can/af_can.c +++ b/trunk/net/can/af_can.c @@ -114,8 +114,7 @@ static void can_sock_destruct(struct sock *sk) skb_queue_purge(&sk->sk_receive_queue); } -static int can_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int can_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; struct can_proto *cp; @@ -161,6 +160,11 @@ static int can_create(struct net *net, struct socket *sock, int protocol, goto errout; } + if (cp->capability >= 0 && !capable(cp->capability)) { + err = -EPERM; + goto errout; + } + sock->ops = cp->ops; sk = sk_alloc(net, PF_CAN, GFP_KERNEL, cp->prot); diff --git a/trunk/net/can/bcm.c b/trunk/net/can/bcm.c index e32af52238a2..2f47039c79dd 100644 --- a/trunk/net/can/bcm.c +++ b/trunk/net/can/bcm.c @@ -132,27 +132,23 @@ static inline struct bcm_sock *bcm_sk(const struct sock *sk) /* * procfs functions */ -static char *bcm_proc_getifname(char *result, int ifindex) +static char *bcm_proc_getifname(int ifindex) { struct net_device *dev; if (!ifindex) return "any"; - rcu_read_lock(); - dev = dev_get_by_index_rcu(&init_net, ifindex); + /* no usage counting */ + dev = __dev_get_by_index(&init_net, ifindex); if (dev) - strcpy(result, dev->name); - else - strcpy(result, "???"); - rcu_read_unlock(); + return dev->name; - return result; + return "???"; } static int bcm_proc_show(struct seq_file *m, void *v) { - char ifname[IFNAMSIZ]; struct sock *sk = (struct sock *)m->private; struct bcm_sock *bo = bcm_sk(sk); struct bcm_op *op; @@ -161,7 +157,7 @@ static int bcm_proc_show(struct seq_file *m, void *v) seq_printf(m, " / sk %p", sk); seq_printf(m, " / bo %p", bo); seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs); - seq_printf(m, " / bound %s", bcm_proc_getifname(ifname, bo->ifindex)); + seq_printf(m, " / bound %s", bcm_proc_getifname(bo->ifindex)); seq_printf(m, " <<<\n"); list_for_each_entry(op, &bo->rx_ops, list) { @@ -173,7 +169,7 @@ static int bcm_proc_show(struct seq_file *m, void *v) continue; seq_printf(m, "rx_op: %03X %-5s ", - op->can_id, bcm_proc_getifname(ifname, op->ifindex)); + op->can_id, bcm_proc_getifname(op->ifindex)); seq_printf(m, "[%d]%c ", op->nframes, (op->flags & RX_CHECK_DLC)?'d':' '); if (op->kt_ival1.tv64) @@ -198,8 +194,7 @@ static int bcm_proc_show(struct seq_file *m, void *v) list_for_each_entry(op, &bo->tx_ops, list) { seq_printf(m, "tx_op: %03X %s [%d] ", - op->can_id, - bcm_proc_getifname(ifname, op->ifindex), + op->can_id, bcm_proc_getifname(op->ifindex), op->nframes); if (op->kt_ival1.tv64) @@ -1581,6 +1576,7 @@ static struct proto bcm_proto __read_mostly = { static struct can_proto bcm_can_proto __read_mostly = { .type = SOCK_DGRAM, .protocol = CAN_BCM, + .capability = -1, .ops = &bcm_ops, .prot = &bcm_proto, }; diff --git a/trunk/net/can/raw.c b/trunk/net/can/raw.c index abca920440b5..6e77db58b9e6 100644 --- a/trunk/net/can/raw.c +++ b/trunk/net/can/raw.c @@ -742,6 +742,7 @@ static struct proto raw_proto __read_mostly = { static struct can_proto raw_can_proto __read_mostly = { .type = SOCK_RAW, .protocol = CAN_RAW, + .capability = -1, .ops = &raw_ops, .prot = &raw_proto, }; diff --git a/trunk/net/core/datagram.c b/trunk/net/core/datagram.c index 95c2e0840d0d..4d57f5e12b05 100644 --- a/trunk/net/core/datagram.c +++ b/trunk/net/core/datagram.c @@ -224,15 +224,6 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb) consume_skb(skb); sk_mem_reclaim_partial(sk); } -EXPORT_SYMBOL(skb_free_datagram); - -void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb) -{ - lock_sock(sk); - skb_free_datagram(sk, skb); - release_sock(sk); -} -EXPORT_SYMBOL(skb_free_datagram_locked); /** * skb_kill_datagram - Free a datagram skbuff forcibly @@ -762,4 +753,5 @@ unsigned int datagram_poll(struct file *file, struct socket *sock, EXPORT_SYMBOL(datagram_poll); EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec); EXPORT_SYMBOL(skb_copy_datagram_iovec); +EXPORT_SYMBOL(skb_free_datagram); EXPORT_SYMBOL(skb_recv_datagram); diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 548340b57296..bf629ac08b87 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -79,7 +79,6 @@ #include #include #include -#include #include #include #include @@ -197,7 +196,7 @@ EXPORT_SYMBOL(dev_base_lock); static inline struct hlist_head *dev_name_hash(struct net *net, const char *name) { unsigned hash = full_name_hash(name, strnlen(name, IFNAMSIZ)); - return &net->dev_name_head[hash_32(hash, NETDEV_HASHBITS)]; + return &net->dev_name_head[hash & (NETDEV_HASHENTRIES - 1)]; } static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex) @@ -1757,7 +1756,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, struct netdev_queue *txq) { const struct net_device_ops *ops = dev->netdev_ops; - int rc = NETDEV_TX_OK; + int rc; if (likely(!skb->next)) { if (!list_empty(&ptype_all)) @@ -1805,8 +1804,6 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, nskb->next = NULL; rc = ops->ndo_start_xmit(nskb, dev); if (unlikely(rc != NETDEV_TX_OK)) { - if (rc & ~NETDEV_TX_MASK) - goto out_kfree_gso_skb; nskb->next = skb->next; skb->next = nskb; return rc; @@ -1816,12 +1813,11 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, return NETDEV_TX_BUSY; } while (skb->next); -out_kfree_gso_skb: - if (likely(skb->next == NULL)) - skb->destructor = DEV_GSO_CB(skb)->destructor; + skb->destructor = DEV_GSO_CB(skb)->destructor; + out_kfree_skb: kfree_skb(skb); - return rc; + return NETDEV_TX_OK; } static u32 skb_tx_hashrnd; @@ -1909,23 +1905,6 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, return rc; } -static inline bool dev_xmit_complete(int rc) -{ - /* successful transmission */ - if (rc == NETDEV_TX_OK) - return true; - - /* error while transmitting, driver consumed skb */ - if (rc < 0) - return true; - - /* error while queueing to a different device, driver consumed skb */ - if (rc & NET_XMIT_MASK) - return true; - - return false; -} - /** * dev_queue_xmit - transmit a buffer * @skb: buffer to transmit @@ -2023,8 +2002,8 @@ int dev_queue_xmit(struct sk_buff *skb) HARD_TX_LOCK(dev, txq, cpu); if (!netif_tx_queue_stopped(txq)) { - rc = dev_hard_start_xmit(skb, dev, txq); - if (dev_xmit_complete(rc)) { + rc = NET_XMIT_SUCCESS; + if (!dev_hard_start_xmit(skb, dev, txq)) { HARD_TX_UNLOCK(dev, txq); goto out; } diff --git a/trunk/net/core/drop_monitor.c b/trunk/net/core/drop_monitor.c index b8e9d3a86887..0a113f26bc9f 100644 --- a/trunk/net/core/drop_monitor.c +++ b/trunk/net/core/drop_monitor.c @@ -41,7 +41,7 @@ static void send_dm_alert(struct work_struct *unused); * netlink alerts */ static int trace_state = TRACE_OFF; -static DEFINE_SPINLOCK(trace_state_lock); +static spinlock_t trace_state_lock = SPIN_LOCK_UNLOCKED; struct per_cpu_dm_data { struct work_struct dm_alert_work; diff --git a/trunk/net/core/pktgen.c b/trunk/net/core/pktgen.c index d38470a32792..5ce017bf4afa 100644 --- a/trunk/net/core/pktgen.c +++ b/trunk/net/core/pktgen.c @@ -340,7 +340,6 @@ struct pktgen_dev { __u16 cur_udp_src; __u16 cur_queue_map; __u32 cur_pkt_size; - __u32 last_pkt_size; __u8 hh[14]; /* = { @@ -3435,7 +3434,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) pkt_dev->clone_count--; /* back out increment, OOM */ return; } - pkt_dev->last_pkt_size = pkt_dev->skb->len; + pkt_dev->allocated_skbs++; pkt_dev->clone_count = 0; /* reset counter */ } @@ -3462,7 +3461,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) pkt_dev->last_ok = 1; pkt_dev->sofar++; pkt_dev->seq_num++; - pkt_dev->tx_bytes += pkt_dev->last_pkt_size; + pkt_dev->tx_bytes += pkt_dev->cur_pkt_size; break; default: /* Drivers are not supposed to return other values! */ if (net_ratelimit()) diff --git a/trunk/net/core/rtnetlink.c b/trunk/net/core/rtnetlink.c index 33148a568199..391a62cd9df6 100644 --- a/trunk/net/core/rtnetlink.c +++ b/trunk/net/core/rtnetlink.c @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -52,7 +53,8 @@ #include #include -struct rtnl_link { +struct rtnl_link +{ rtnl_doit_func doit; rtnl_dumpit_func dumpit; }; @@ -63,7 +65,6 @@ void rtnl_lock(void) { mutex_lock(&rtnl_mutex); } -EXPORT_SYMBOL(rtnl_lock); void __rtnl_unlock(void) { @@ -75,19 +76,16 @@ void rtnl_unlock(void) /* This fellow will unlock it for us. */ netdev_run_todo(); } -EXPORT_SYMBOL(rtnl_unlock); int rtnl_trylock(void) { return mutex_trylock(&rtnl_mutex); } -EXPORT_SYMBOL(rtnl_trylock); int rtnl_is_locked(void) { return mutex_is_locked(&rtnl_mutex); } -EXPORT_SYMBOL(rtnl_is_locked); static struct rtnl_link *rtnl_msg_handlers[NPROTO]; @@ -170,6 +168,7 @@ int __rtnl_register(int protocol, int msgtype, return 0; } + EXPORT_SYMBOL_GPL(__rtnl_register); /** @@ -189,6 +188,7 @@ void rtnl_register(int protocol, int msgtype, "protocol = %d, message type = %d\n", protocol, msgtype); } + EXPORT_SYMBOL_GPL(rtnl_register); /** @@ -213,6 +213,7 @@ int rtnl_unregister(int protocol, int msgtype) return 0; } + EXPORT_SYMBOL_GPL(rtnl_unregister); /** @@ -229,6 +230,7 @@ void rtnl_unregister_all(int protocol) kfree(rtnl_msg_handlers[protocol]); rtnl_msg_handlers[protocol] = NULL; } + EXPORT_SYMBOL_GPL(rtnl_unregister_all); static LIST_HEAD(link_ops); @@ -251,6 +253,7 @@ int __rtnl_link_register(struct rtnl_link_ops *ops) list_add_tail(&ops->list, &link_ops); return 0; } + EXPORT_SYMBOL_GPL(__rtnl_link_register); /** @@ -268,6 +271,7 @@ int rtnl_link_register(struct rtnl_link_ops *ops) rtnl_unlock(); return err; } + EXPORT_SYMBOL_GPL(rtnl_link_register); static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops) @@ -305,6 +309,7 @@ void __rtnl_link_unregister(struct rtnl_link_ops *ops) } list_del(&ops->list); } + EXPORT_SYMBOL_GPL(__rtnl_link_unregister); /** @@ -317,6 +322,7 @@ void rtnl_link_unregister(struct rtnl_link_ops *ops) __rtnl_link_unregister(ops); rtnl_unlock(); } + EXPORT_SYMBOL_GPL(rtnl_link_unregister); static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) @@ -421,13 +427,12 @@ void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data struct rtattr *rta; int size = RTA_LENGTH(attrlen); - rta = (struct rtattr *)skb_put(skb, RTA_ALIGN(size)); + rta = (struct rtattr*)skb_put(skb, RTA_ALIGN(size)); rta->rta_type = attrtype; rta->rta_len = size; memcpy(RTA_DATA(rta), data, attrlen); memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size); } -EXPORT_SYMBOL(__rta_fill); int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo) { @@ -449,7 +454,6 @@ int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid) return nlmsg_unicast(rtnl, skb, pid); } -EXPORT_SYMBOL(rtnl_unicast); void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, struct nlmsghdr *nlh, gfp_t flags) @@ -462,7 +466,6 @@ void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, nlmsg_notify(rtnl, skb, pid, group, report, flags); } -EXPORT_SYMBOL(rtnl_notify); void rtnl_set_sk_err(struct net *net, u32 group, int error) { @@ -470,7 +473,6 @@ void rtnl_set_sk_err(struct net *net, u32 group, int error) netlink_set_err(rtnl, 0, group, error); } -EXPORT_SYMBOL(rtnl_set_sk_err); int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) { @@ -499,7 +501,6 @@ int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) nla_nest_cancel(skb, mx); return -EMSGSIZE; } -EXPORT_SYMBOL(rtnetlink_put_metrics); int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, u32 ts, u32 tsage, long expires, u32 error) @@ -519,13 +520,14 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, return nla_put(skb, RTA_CACHEINFO, sizeof(ci), &ci); } + EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo); static void set_operstate(struct net_device *dev, unsigned char transition) { unsigned char operstate = dev->operstate; - switch (transition) { + switch(transition) { case IF_OPER_UP: if ((operstate == IF_OPER_DORMANT || operstate == IF_OPER_UNKNOWN) && @@ -726,27 +728,12 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { [IFLA_NET_NS_PID] = { .type = NLA_U32 }, [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, }; -EXPORT_SYMBOL(ifla_policy); static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { [IFLA_INFO_KIND] = { .type = NLA_STRING }, [IFLA_INFO_DATA] = { .type = NLA_NESTED }, }; -struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) -{ - struct net *net; - /* Examine the link attributes and figure out which - * network namespace we are talking about. - */ - if (tb[IFLA_NET_NS_PID]) - net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); - else - net = get_net(src_net); - return net; -} -EXPORT_SYMBOL(rtnl_link_get_net); - static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) { if (dev) { @@ -770,7 +757,8 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, int err; if (tb[IFLA_NET_NS_PID]) { - struct net *net = rtnl_link_get_net(dev_net(dev), tb); + struct net *net; + net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); if (IS_ERR(net)) { err = PTR_ERR(net); goto errout; @@ -944,8 +932,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) goto errout; } - err = validate_linkmsg(dev, tb); - if (err < 0) + if ((err = validate_linkmsg(dev, tb)) < 0) goto errout; err = do_setlink(dev, ifm, tb, ifname, 0); @@ -989,8 +976,8 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) return 0; } -struct net_device *rtnl_create_link(struct net *src_net, struct net *net, - char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]) +struct net_device *rtnl_create_link(struct net *net, char *ifname, + const struct rtnl_link_ops *ops, struct nlattr *tb[]) { int err; struct net_device *dev; @@ -998,8 +985,7 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net, unsigned int real_num_queues = 1; if (ops->get_tx_queues) { - err = ops->get_tx_queues(src_net, tb, &num_queues, - &real_num_queues); + err = ops->get_tx_queues(net, tb, &num_queues, &real_num_queues); if (err) goto err; } @@ -1008,16 +994,16 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net, if (!dev) goto err; - dev_net_set(dev, net); - dev->rtnl_link_ops = ops; dev->real_num_tx_queues = real_num_queues; - if (strchr(dev->name, '%')) { err = dev_alloc_name(dev, dev->name); if (err < 0) goto err_free; } + dev_net_set(dev, net); + dev->rtnl_link_ops = ops; + if (tb[IFLA_MTU]) dev->mtu = nla_get_u32(tb[IFLA_MTU]); if (tb[IFLA_ADDRESS]) @@ -1040,7 +1026,6 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net, err: return ERR_PTR(err); } -EXPORT_SYMBOL(rtnl_create_link); static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { @@ -1074,8 +1059,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) else dev = NULL; - err = validate_linkmsg(dev, tb); - if (err < 0) + if ((err = validate_linkmsg(dev, tb)) < 0) return err; if (tb[IFLA_LINKINFO]) { @@ -1096,7 +1080,6 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) if (1) { struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL; - struct net *dest_net; if (ops) { if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { @@ -1161,19 +1144,17 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) if (!ifname[0]) snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); - dest_net = rtnl_link_get_net(net, tb); - dev = rtnl_create_link(net, dest_net, ifname, ops, tb); + dev = rtnl_create_link(net, ifname, ops, tb); if (IS_ERR(dev)) err = PTR_ERR(dev); else if (ops->newlink) - err = ops->newlink(net, dev, tb, data); + err = ops->newlink(dev, tb, data); else err = register_netdevice(dev); + if (err < 0 && !IS_ERR(dev)) free_netdev(dev); - - put_net(dest_net); return err; } } @@ -1229,7 +1210,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) if (s_idx == 0) s_idx = 1; - for (idx = 1; idx < NPROTO; idx++) { + for (idx=1; idxnlh->nlmsg_type-RTM_BASE; if (idx < s_idx || idx == PF_PACKET) continue; @@ -1296,7 +1277,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg))) return 0; - family = ((struct rtgenmsg *)NLMSG_DATA(nlh))->rtgen_family; + family = ((struct rtgenmsg*)NLMSG_DATA(nlh))->rtgen_family; if (family >= NPROTO) return -EAFNOSUPPORT; @@ -1329,7 +1310,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (nlh->nlmsg_len > min_len) { int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); - struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len); + struct rtattr *attr = (void*)nlh + NLMSG_ALIGN(min_len); while (RTA_OK(attr, attrlen)) { unsigned flavor = attr->rta_type; @@ -1435,3 +1416,14 @@ void __init rtnetlink_init(void) rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all); } +EXPORT_SYMBOL(__rta_fill); +EXPORT_SYMBOL(rtnetlink_put_metrics); +EXPORT_SYMBOL(rtnl_lock); +EXPORT_SYMBOL(rtnl_trylock); +EXPORT_SYMBOL(rtnl_unlock); +EXPORT_SYMBOL(rtnl_is_locked); +EXPORT_SYMBOL(rtnl_unicast); +EXPORT_SYMBOL(rtnl_notify); +EXPORT_SYMBOL(rtnl_set_sk_err); +EXPORT_SYMBOL(rtnl_create_link); +EXPORT_SYMBOL(ifla_policy); diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index 941bac907484..80a96166df39 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -493,9 +493,6 @@ int skb_recycle_check(struct sk_buff *skb, int skb_size) { struct skb_shared_info *shinfo; - if (irqs_disabled()) - return 0; - if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE) return 0; diff --git a/trunk/net/core/sock.c b/trunk/net/core/sock.c index 76ff58d43e26..5a51512f638a 100644 --- a/trunk/net/core/sock.c +++ b/trunk/net/core/sock.c @@ -417,18 +417,17 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen) if (copy_from_user(devname, optval, optlen)) goto out; - index = 0; - if (devname[0] != '\0') { - struct net_device *dev; - - rcu_read_lock(); - dev = dev_get_by_name_rcu(net, devname); - if (dev) - index = dev->ifindex; - rcu_read_unlock(); + if (devname[0] == '\0') { + index = 0; + } else { + struct net_device *dev = dev_get_by_name(net, devname); + ret = -ENODEV; if (!dev) goto out; + + index = dev->ifindex; + dev_put(dev); } lock_sock(sk); diff --git a/trunk/net/dccp/ipv4.c b/trunk/net/dccp/ipv4.c index 2423a0866733..00028d4b09d9 100644 --- a/trunk/net/dccp/ipv4.c +++ b/trunk/net/dccp/ipv4.c @@ -991,6 +991,7 @@ static struct inet_protosw dccp_v4_protosw = { .protocol = IPPROTO_DCCP, .prot = &dccp_v4_prot, .ops = &inet_dccp_ops, + .capability = -1, .no_check = 0, .flags = INET_PROTOSW_ICSK, }; diff --git a/trunk/net/dccp/ipv6.c b/trunk/net/dccp/ipv6.c index 50ea91a77705..6d89f9f7d5d8 100644 --- a/trunk/net/dccp/ipv6.c +++ b/trunk/net/dccp/ipv6.c @@ -1185,6 +1185,7 @@ static struct inet_protosw dccp_v6_protosw = { .protocol = IPPROTO_DCCP, .prot = &dccp_v6_prot, .ops = &inet6_dccp_ops, + .capability = -1, .flags = INET_PROTOSW_ICSK, }; diff --git a/trunk/net/decnet/af_decnet.c b/trunk/net/decnet/af_decnet.c index 9ade3a6de954..2e355841ca99 100644 --- a/trunk/net/decnet/af_decnet.c +++ b/trunk/net/decnet/af_decnet.c @@ -675,8 +675,7 @@ char *dn_addr2asc(__u16 addr, char *buf) -static int dn_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int dn_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; diff --git a/trunk/net/decnet/dn_dev.c b/trunk/net/decnet/dn_dev.c index 6c916e2b8a84..d82694d930b4 100644 --- a/trunk/net/decnet/dn_dev.c +++ b/trunk/net/decnet/dn_dev.c @@ -68,7 +68,7 @@ extern struct neigh_table dn_neigh_table; */ __le16 decnet_address = 0; -static DEFINE_SPINLOCK(dndev_lock); +static DEFINE_RWLOCK(dndev_lock); static struct net_device *decnet_default_device; static BLOCKING_NOTIFIER_HEAD(dnaddr_chain); @@ -557,8 +557,7 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg) struct net_device *dn_dev_get_default(void) { struct net_device *dev; - - spin_lock(&dndev_lock); + read_lock(&dndev_lock); dev = decnet_default_device; if (dev) { if (dev->dn_ptr) @@ -566,8 +565,7 @@ struct net_device *dn_dev_get_default(void) else dev = NULL; } - spin_unlock(&dndev_lock); - + read_unlock(&dndev_lock); return dev; } @@ -577,15 +575,13 @@ int dn_dev_set_default(struct net_device *dev, int force) int rv = -EBUSY; if (!dev->dn_ptr) return -ENODEV; - - spin_lock(&dndev_lock); + write_lock(&dndev_lock); if (force || decnet_default_device == NULL) { old = decnet_default_device; decnet_default_device = dev; rv = 0; } - spin_unlock(&dndev_lock); - + write_unlock(&dndev_lock); if (old) dev_put(old); return rv; @@ -593,14 +589,13 @@ int dn_dev_set_default(struct net_device *dev, int force) static void dn_dev_check_default(struct net_device *dev) { - spin_lock(&dndev_lock); + write_lock(&dndev_lock); if (dev == decnet_default_device) { decnet_default_device = NULL; } else { dev = NULL; } - spin_unlock(&dndev_lock); - + write_unlock(&dndev_lock); if (dev) dev_put(dev); } @@ -833,17 +828,13 @@ static int dn_dev_get_first(struct net_device *dev, __le16 *addr) struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; struct dn_ifaddr *ifa; int rv = -ENODEV; - if (dn_db == NULL) goto out; - - rtnl_lock(); ifa = dn_db->ifa_list; if (ifa != NULL) { *addr = ifa->ifa_local; rv = 0; } - rtnl_unlock(); out: return rv; } @@ -865,7 +856,9 @@ int dn_dev_bind_default(__le16 *addr) dev = dn_dev_get_default(); last_chance: if (dev) { + read_lock(&dev_base_lock); rv = dn_dev_get_first(dev, addr); + read_unlock(&dev_base_lock); dev_put(dev); if (rv == 0 || dev == init_net.loopback_dev) return rv; @@ -1330,18 +1323,18 @@ static inline int is_dn_dev(struct net_device *dev) } static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(rcu) + __acquires(&dev_base_lock) { int i; struct net_device *dev; - rcu_read_lock(); + read_lock(&dev_base_lock); if (*pos == 0) return SEQ_START_TOKEN; i = 1; - for_each_netdev_rcu(&init_net, dev) { + for_each_netdev(&init_net, dev) { if (!is_dn_dev(dev)) continue; @@ -1362,7 +1355,7 @@ static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) if (v == SEQ_START_TOKEN) dev = net_device_entry(&init_net.dev_base_head); - for_each_netdev_continue_rcu(&init_net, dev) { + for_each_netdev_continue(&init_net, dev) { if (!is_dn_dev(dev)) continue; @@ -1373,9 +1366,9 @@ static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void dn_dev_seq_stop(struct seq_file *seq, void *v) - __releases(rcu) + __releases(&dev_base_lock) { - rcu_read_unlock(); + read_unlock(&dev_base_lock); } static char *dn_type2asc(char type) diff --git a/trunk/net/decnet/sysctl_net_decnet.c b/trunk/net/decnet/sysctl_net_decnet.c index 2036568beea9..26b0ab1e9f56 100644 --- a/trunk/net/decnet/sysctl_net_decnet.c +++ b/trunk/net/decnet/sysctl_net_decnet.c @@ -263,10 +263,11 @@ static int dn_def_dev_strategy(ctl_table *table, return -ENODEV; rv = -ENODEV; - if (dev->dn_ptr != NULL) + if (dev->dn_ptr != NULL) { rv = dn_dev_set_default(dev, 1); - if (rv) - dev_put(dev); + if (rv) + dev_put(dev); + } } return rv; diff --git a/trunk/net/econet/af_econet.c b/trunk/net/econet/af_econet.c index 596679803de5..5e9426a11c3e 100644 --- a/trunk/net/econet/af_econet.c +++ b/trunk/net/econet/af_econet.c @@ -605,8 +605,7 @@ static struct proto econet_proto = { * Create an Econet socket */ -static int econet_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int econet_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; struct econet_sock *eo; diff --git a/trunk/net/ieee802154/af_ieee802154.c b/trunk/net/ieee802154/af_ieee802154.c index de6e34d2a7f8..309348fba72b 100644 --- a/trunk/net/ieee802154/af_ieee802154.c +++ b/trunk/net/ieee802154/af_ieee802154.c @@ -234,7 +234,7 @@ static const struct proto_ops ieee802154_dgram_ops = { * set the state. */ static int ieee802154_create(struct net *net, struct socket *sock, - int protocol, int kern) + int protocol) { struct sock *sk; int rc; diff --git a/trunk/net/ieee802154/wpan-class.c b/trunk/net/ieee802154/wpan-class.c index 38bac70cca10..268691256a6d 100644 --- a/trunk/net/ieee802154/wpan-class.c +++ b/trunk/net/ieee802154/wpan-class.c @@ -205,7 +205,7 @@ static int __init wpan_phy_class_init(void) err: return rc; } -module_init(wpan_phy_class_init); +subsys_initcall(wpan_phy_class_init); static void __exit wpan_phy_class_exit(void) { diff --git a/trunk/net/ipv4/af_inet.c b/trunk/net/ipv4/af_inet.c index 7d12c6a9b19b..538e84d0bcba 100644 --- a/trunk/net/ipv4/af_inet.c +++ b/trunk/net/ipv4/af_inet.c @@ -262,8 +262,7 @@ static inline int inet_netns_ok(struct net *net, int protocol) * Create an inet socket. */ -static int inet_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int inet_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; struct inet_protosw *answer; @@ -326,7 +325,7 @@ static int inet_create(struct net *net, struct socket *sock, int protocol, } err = -EPERM; - if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) + if (answer->capability > 0 && !capable(answer->capability)) goto out_rcu_unlock; err = -EAFNOSUPPORT; @@ -948,6 +947,7 @@ static struct inet_protosw inetsw_array[] = .protocol = IPPROTO_TCP, .prot = &tcp_prot, .ops = &inet_stream_ops, + .capability = -1, .no_check = 0, .flags = INET_PROTOSW_PERMANENT | INET_PROTOSW_ICSK, @@ -958,6 +958,7 @@ static struct inet_protosw inetsw_array[] = .protocol = IPPROTO_UDP, .prot = &udp_prot, .ops = &inet_dgram_ops, + .capability = -1, .no_check = UDP_CSUM_DEFAULT, .flags = INET_PROTOSW_PERMANENT, }, @@ -968,6 +969,7 @@ static struct inet_protosw inetsw_array[] = .protocol = IPPROTO_IP, /* wild card */ .prot = &raw_prot, .ops = &inet_sockraw_ops, + .capability = CAP_NET_RAW, .no_check = UDP_CSUM_DEFAULT, .flags = INET_PROTOSW_REUSE, } diff --git a/trunk/net/ipv4/devinet.c b/trunk/net/ipv4/devinet.c index 7620382058a0..c2045f9615da 100644 --- a/trunk/net/ipv4/devinet.c +++ b/trunk/net/ipv4/devinet.c @@ -1174,54 +1174,39 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) { struct net *net = sock_net(skb->sk); - int h, s_h; - int idx, s_idx; - int ip_idx, s_ip_idx; + int idx, ip_idx; struct net_device *dev; struct in_device *in_dev; struct in_ifaddr *ifa; - struct hlist_head *head; - struct hlist_node *node; + int s_ip_idx, s_idx = cb->args[0]; - s_h = cb->args[0]; - s_idx = idx = cb->args[1]; - s_ip_idx = ip_idx = cb->args[2]; - - for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { - idx = 0; - head = &net->dev_index_head[h]; - rcu_read_lock(); - hlist_for_each_entry_rcu(dev, node, head, index_hlist) { - if (idx < s_idx) - goto cont; - if (idx > s_idx) - s_ip_idx = 0; - in_dev = __in_dev_get_rcu(dev); - if (!in_dev) - goto cont; + s_ip_idx = ip_idx = cb->args[1]; + idx = 0; + for_each_netdev(net, dev) { + if (idx < s_idx) + goto cont; + if (idx > s_idx) + s_ip_idx = 0; + in_dev = __in_dev_get_rtnl(dev); + if (!in_dev) + goto cont; - for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; - ifa = ifa->ifa_next, ip_idx++) { - if (ip_idx < s_ip_idx) - continue; - if (inet_fill_ifaddr(skb, ifa, - NETLINK_CB(cb->skb).pid, + for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; + ifa = ifa->ifa_next, ip_idx++) { + if (ip_idx < s_ip_idx) + continue; + if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, - RTM_NEWADDR, NLM_F_MULTI) <= 0) { - rcu_read_unlock(); - goto done; - } - } -cont: - idx++; + RTM_NEWADDR, NLM_F_MULTI) <= 0) + goto done; } - rcu_read_unlock(); +cont: + idx++; } done: - cb->args[0] = h; - cb->args[1] = idx; - cb->args[2] = ip_idx; + cb->args[0] = idx; + cb->args[1] = ip_idx; return skb->len; } diff --git a/trunk/net/ipv4/fib_frontend.c b/trunk/net/ipv4/fib_frontend.c index 816e2180bd60..f73dbed0f0d7 100644 --- a/trunk/net/ipv4/fib_frontend.c +++ b/trunk/net/ipv4/fib_frontend.c @@ -229,17 +229,14 @@ unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, */ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, - struct net_device *dev, __be32 *spec_dst, - u32 *itag, u32 mark) + struct net_device *dev, __be32 *spec_dst, u32 *itag) { struct in_device *in_dev; struct flowi fl = { .nl_u = { .ip4_u = { .daddr = src, .saddr = dst, .tos = tos } }, - .mark = mark, .iif = oif }; - struct fib_result res; int no_addr, rpf; int ret; diff --git a/trunk/net/ipv4/igmp.c b/trunk/net/ipv4/igmp.c index 6110c6d6e613..d41e5de79a82 100644 --- a/trunk/net/ipv4/igmp.c +++ b/trunk/net/ipv4/igmp.c @@ -2311,10 +2311,9 @@ static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq) struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq); state->in_dev = NULL; - for_each_netdev_rcu(net, state->dev) { + for_each_netdev(net, state->dev) { struct in_device *in_dev; - - in_dev = __in_dev_get_rcu(state->dev); + in_dev = in_dev_get(state->dev); if (!in_dev) continue; read_lock(&in_dev->mc_list_lock); @@ -2324,6 +2323,7 @@ static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq) break; } read_unlock(&in_dev->mc_list_lock); + in_dev_put(in_dev); } return im; } @@ -2333,15 +2333,16 @@ static struct ip_mc_list *igmp_mc_get_next(struct seq_file *seq, struct ip_mc_li struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq); im = im->next; while (!im) { - if (likely(state->in_dev != NULL)) + if (likely(state->in_dev != NULL)) { read_unlock(&state->in_dev->mc_list_lock); - - state->dev = next_net_device_rcu(state->dev); + in_dev_put(state->in_dev); + } + state->dev = next_net_device(state->dev); if (!state->dev) { state->in_dev = NULL; break; } - state->in_dev = __in_dev_get_rcu(state->dev); + state->in_dev = in_dev_get(state->dev); if (!state->in_dev) continue; read_lock(&state->in_dev->mc_list_lock); @@ -2360,9 +2361,9 @@ static struct ip_mc_list *igmp_mc_get_idx(struct seq_file *seq, loff_t pos) } static void *igmp_mc_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(rcu) + __acquires(dev_base_lock) { - rcu_read_lock(); + read_lock(&dev_base_lock); return *pos ? igmp_mc_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } @@ -2378,15 +2379,16 @@ static void *igmp_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void igmp_mc_seq_stop(struct seq_file *seq, void *v) - __releases(rcu) + __releases(dev_base_lock) { struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq); if (likely(state->in_dev != NULL)) { read_unlock(&state->in_dev->mc_list_lock); + in_dev_put(state->in_dev); state->in_dev = NULL; } state->dev = NULL; - rcu_read_unlock(); + read_unlock(&dev_base_lock); } static int igmp_mc_seq_show(struct seq_file *seq, void *v) @@ -2460,9 +2462,9 @@ static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq) state->idev = NULL; state->im = NULL; - for_each_netdev_rcu(net, state->dev) { + for_each_netdev(net, state->dev) { struct in_device *idev; - idev = __in_dev_get_rcu(state->dev); + idev = in_dev_get(state->dev); if (unlikely(idev == NULL)) continue; read_lock(&idev->mc_list_lock); @@ -2478,6 +2480,7 @@ static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq) spin_unlock_bh(&im->lock); } read_unlock(&idev->mc_list_lock); + in_dev_put(idev); } return psf; } @@ -2491,15 +2494,16 @@ static struct ip_sf_list *igmp_mcf_get_next(struct seq_file *seq, struct ip_sf_l spin_unlock_bh(&state->im->lock); state->im = state->im->next; while (!state->im) { - if (likely(state->idev != NULL)) + if (likely(state->idev != NULL)) { read_unlock(&state->idev->mc_list_lock); - - state->dev = next_net_device_rcu(state->dev); + in_dev_put(state->idev); + } + state->dev = next_net_device(state->dev); if (!state->dev) { state->idev = NULL; goto out; } - state->idev = __in_dev_get_rcu(state->dev); + state->idev = in_dev_get(state->dev); if (!state->idev) continue; read_lock(&state->idev->mc_list_lock); @@ -2524,9 +2528,8 @@ static struct ip_sf_list *igmp_mcf_get_idx(struct seq_file *seq, loff_t pos) } static void *igmp_mcf_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(rcu) { - rcu_read_lock(); + read_lock(&dev_base_lock); return *pos ? igmp_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } @@ -2542,7 +2545,6 @@ static void *igmp_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void igmp_mcf_seq_stop(struct seq_file *seq, void *v) - __releases(rcu) { struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq); if (likely(state->im != NULL)) { @@ -2551,10 +2553,11 @@ static void igmp_mcf_seq_stop(struct seq_file *seq, void *v) } if (likely(state->idev != NULL)) { read_unlock(&state->idev->mc_list_lock); + in_dev_put(state->idev); state->idev = NULL; } state->dev = NULL; - rcu_read_unlock(); + read_unlock(&dev_base_lock); } static int igmp_mcf_seq_show(struct seq_file *seq, void *v) diff --git a/trunk/net/ipv4/inetpeer.c b/trunk/net/ipv4/inetpeer.c index 6bcfe52a9c87..b1fbe18feb5a 100644 --- a/trunk/net/ipv4/inetpeer.c +++ b/trunk/net/ipv4/inetpeer.c @@ -67,6 +67,9 @@ * ip_id_count: idlock */ +/* Exported for inet_getid inline function. */ +DEFINE_SPINLOCK(inet_peer_idlock); + static struct kmem_cache *peer_cachep __read_mostly; #define node_height(x) x->avl_height @@ -387,7 +390,7 @@ struct inet_peer *inet_getpeer(__be32 daddr, int create) n->v4daddr = daddr; atomic_set(&n->refcnt, 1); atomic_set(&n->rid, 0); - atomic_set(&n->ip_id_count, secure_ip_id(daddr)); + n->ip_id_count = secure_ip_id(daddr); n->tcp_ts_stamp = 0; write_lock_bh(&peer_pool_lock); diff --git a/trunk/net/ipv4/ip_fragment.c b/trunk/net/ipv4/ip_fragment.c index b007f8af6e1f..575f9bd51ccd 100644 --- a/trunk/net/ipv4/ip_fragment.c +++ b/trunk/net/ipv4/ip_fragment.c @@ -206,11 +206,10 @@ static void ip_expire(unsigned long arg) struct sk_buff *head = qp->q.fragments; /* Send an ICMP "Fragment Reassembly Timeout" message. */ - rcu_read_lock(); - head->dev = dev_get_by_index_rcu(net, qp->iif); - if (head->dev) + if ((head->dev = dev_get_by_index(net, qp->iif)) != NULL) { icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); - rcu_read_unlock(); + dev_put(head->dev); + } } out: spin_unlock(&qp->q.lock); diff --git a/trunk/net/ipv4/ip_gre.c b/trunk/net/ipv4/ip_gre.c index a7de9e3a8f18..a77807d449e3 100644 --- a/trunk/net/ipv4/ip_gre.c +++ b/trunk/net/ipv4/ip_gre.c @@ -1476,14 +1476,14 @@ static void ipgre_tap_setup(struct net_device *dev) ether_setup(dev); - dev->netdev_ops = &ipgre_tap_netdev_ops; + dev->netdev_ops = &ipgre_netdev_ops; dev->destructor = free_netdev; dev->iflink = 0; dev->features |= NETIF_F_NETNS_LOCAL; } -static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], +static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { struct ip_tunnel *nt; @@ -1537,29 +1537,25 @@ static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], if (t->dev != dev) return -EEXIST; } else { - t = nt; + unsigned nflags = 0; - if (dev->type != ARPHRD_ETHER) { - unsigned nflags = 0; + t = nt; - if (ipv4_is_multicast(p.iph.daddr)) - nflags = IFF_BROADCAST; - else if (p.iph.daddr) - nflags = IFF_POINTOPOINT; + if (ipv4_is_multicast(p.iph.daddr)) + nflags = IFF_BROADCAST; + else if (p.iph.daddr) + nflags = IFF_POINTOPOINT; - if ((dev->flags ^ nflags) & - (IFF_POINTOPOINT | IFF_BROADCAST)) - return -EINVAL; - } + if ((dev->flags ^ nflags) & + (IFF_POINTOPOINT | IFF_BROADCAST)) + return -EINVAL; ipgre_tunnel_unlink(ign, t); t->parms.iph.saddr = p.iph.saddr; t->parms.iph.daddr = p.iph.daddr; t->parms.i_key = p.i_key; - if (dev->type != ARPHRD_ETHER) { - memcpy(dev->dev_addr, &p.iph.saddr, 4); - memcpy(dev->broadcast, &p.iph.daddr, 4); - } + memcpy(dev->dev_addr, &p.iph.saddr, 4); + memcpy(dev->broadcast, &p.iph.daddr, 4); ipgre_tunnel_link(ign, t); netdev_state_change(dev); } diff --git a/trunk/net/ipv4/ipip.c b/trunk/net/ipv4/ipip.c index c5b1f71c3cd8..a2ca53da4372 100644 --- a/trunk/net/ipv4/ipip.c +++ b/trunk/net/ipv4/ipip.c @@ -446,27 +446,25 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) goto tx_error; } - df |= old_iph->frag_off & htons(IP_DF); - - if (df) { + if (tiph->frag_off) mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); + else + mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; - if (mtu < 68) { - stats->collisions++; - ip_rt_put(rt); - goto tx_error; - } + if (mtu < 68) { + stats->collisions++; + ip_rt_put(rt); + goto tx_error; + } + if (skb_dst(skb)) + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); - if (skb_dst(skb)) - skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); + df |= (old_iph->frag_off&htons(IP_DF)); - if ((old_iph->frag_off & htons(IP_DF)) && - mtu < ntohs(old_iph->tot_len)) { - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, - htonl(mtu)); - ip_rt_put(rt); - goto tx_error; - } + if ((old_iph->frag_off&htons(IP_DF)) && mtu < ntohs(old_iph->tot_len)) { + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); + ip_rt_put(rt); + goto tx_error; } if (tunnel->err_count > 0) { diff --git a/trunk/net/ipv4/netfilter/nf_nat_core.c b/trunk/net/ipv4/netfilter/nf_nat_core.c index fe1a64479dd0..68afc6ecd343 100644 --- a/trunk/net/ipv4/netfilter/nf_nat_core.c +++ b/trunk/net/ipv4/netfilter/nf_nat_core.c @@ -750,8 +750,6 @@ static int __init nf_nat_init(void) BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, nfnetlink_parse_nat_setup); - BUG_ON(nf_ct_nat_offset != NULL); - rcu_assign_pointer(nf_ct_nat_offset, nf_nat_get_offset); return 0; cleanup_extend: @@ -766,7 +764,6 @@ static void __exit nf_nat_cleanup(void) nf_ct_extend_unregister(&nat_extend); rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL); rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, NULL); - rcu_assign_pointer(nf_ct_nat_offset, NULL); synchronize_net(); } diff --git a/trunk/net/ipv4/netfilter/nf_nat_helper.c b/trunk/net/ipv4/netfilter/nf_nat_helper.c index f9520fa3aba9..09172a65d9b6 100644 --- a/trunk/net/ipv4/netfilter/nf_nat_helper.c +++ b/trunk/net/ipv4/netfilter/nf_nat_helper.c @@ -73,28 +73,6 @@ adjust_tcp_sequence(u32 seq, DUMP_OFFSET(this_way); } -/* Get the offset value, for conntrack */ -s16 nf_nat_get_offset(const struct nf_conn *ct, - enum ip_conntrack_dir dir, - u32 seq) -{ - struct nf_conn_nat *nat = nfct_nat(ct); - struct nf_nat_seq *this_way; - s16 offset; - - if (!nat) - return 0; - - this_way = &nat->seq[dir]; - spin_lock_bh(&nf_nat_seqofs_lock); - offset = after(seq, this_way->correction_pos) - ? this_way->offset_after : this_way->offset_before; - spin_unlock_bh(&nf_nat_seqofs_lock); - - return offset; -} -EXPORT_SYMBOL_GPL(nf_nat_get_offset); - /* Frobs data inside this packet, which is linear. */ static void mangle_contents(struct sk_buff *skb, unsigned int dataoff, @@ -211,6 +189,11 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb, adjust_tcp_sequence(ntohl(tcph->seq), (int)rep_len - (int)match_len, ct, ctinfo); + /* Tell TCP window tracking about seq change */ + nf_conntrack_tcp_update(skb, ip_hdrlen(skb), + ct, CTINFO2DIR(ctinfo), + (int)rep_len - (int)match_len); + nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); } return 1; @@ -432,7 +415,12 @@ nf_nat_seq_adjust(struct sk_buff *skb, tcph->seq = newseq; tcph->ack_seq = newack; - return nf_nat_sack_adjust(skb, tcph, ct, ctinfo); + if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo)) + return 0; + + nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir, seqoff); + + return 1; } /* Setup NAT on this expected conntrack so it follows master. */ diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index 4284ceef7945..68fb22702051 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -1851,7 +1851,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, goto e_inval; spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); } else if (fib_validate_source(saddr, 0, tos, 0, - dev, &spec_dst, &itag, 0) < 0) + dev, &spec_dst, &itag) < 0) goto e_inval; rth = dst_alloc(&ipv4_dst_ops); @@ -1964,7 +1964,7 @@ static int __mkroute_input(struct sk_buff *skb, err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res), - in_dev->dev, &spec_dst, &itag, skb->mark); + in_dev->dev, &spec_dst, &itag); if (err < 0) { ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, saddr); @@ -2138,7 +2138,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, int result; result = fib_validate_source(saddr, daddr, tos, net->loopback_dev->ifindex, - dev, &spec_dst, &itag, skb->mark); + dev, &spec_dst, &itag); if (result < 0) goto martian_source; if (result) @@ -2167,7 +2167,7 @@ out: return err; spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); else { err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, - &itag, skb->mark); + &itag); if (err < 0) goto martian_source; if (err) @@ -2852,7 +2852,7 @@ static int rt_fill_info(struct net *net, error = rt->u.dst.error; expires = rt->u.dst.expires ? rt->u.dst.expires - jiffies : 0; if (rt->peer) { - id = atomic_read(&rt->peer->ip_id_count) & 0xffff; + id = rt->peer->ip_id_count; if (rt->peer->tcp_ts_stamp) { ts = rt->peer->tcp_ts; tsage = get_seconds() - rt->peer->tcp_ts_stamp; diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index cc306ac6eb51..be0c5bf7bfca 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -140,7 +140,7 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb) * "len" is invariant segment length, including TCP header. */ len += skb->data - skb_transport_header(skb); - if (len >= TCP_MSS_DEFAULT + sizeof(struct tcphdr) || + if (len >= TCP_MIN_RCVMSS + sizeof(struct tcphdr) || /* If PSH is not set, packet should be * full sized, provided peer TCP is not badly broken. * This observation (if it is correct 8)) allows @@ -411,7 +411,7 @@ void tcp_initialize_rcv_mss(struct sock *sk) unsigned int hint = min_t(unsigned int, tp->advmss, tp->mss_cache); hint = min(hint, tp->rcv_wnd / 2); - hint = min(hint, TCP_MSS_DEFAULT); + hint = min(hint, TCP_MIN_RCVMSS); hint = max(hint, TCP_MIN_MSS); inet_csk(sk)->icsk_ack.rcv_mss = hint; diff --git a/trunk/net/ipv4/tcp_ipv4.c b/trunk/net/ipv4/tcp_ipv4.c index df18ce04f41e..657ae334f125 100644 --- a/trunk/net/ipv4/tcp_ipv4.c +++ b/trunk/net/ipv4/tcp_ipv4.c @@ -204,7 +204,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) * when trying new connection. */ if (peer != NULL && - (u32)get_seconds() - peer->tcp_ts_stamp <= TCP_PAWS_MSL) { + peer->tcp_ts_stamp + TCP_PAWS_MSL >= get_seconds()) { tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp; tp->rx_opt.ts_recent = peer->tcp_ts; } @@ -217,7 +217,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (inet->opt) inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen; - tp->rx_opt.mss_clamp = TCP_MSS_DEFAULT; + tp->rx_opt.mss_clamp = 536; /* Socket identity is still unknown (sport may be zero). * However we set state to SYN-SENT and not releasing socket @@ -1268,7 +1268,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) goto drop_and_free; tcp_clear_options(&tmp_opt); - tmp_opt.mss_clamp = TCP_MSS_DEFAULT; + tmp_opt.mss_clamp = 536; tmp_opt.user_mss = tcp_sk(sk)->rx_opt.user_mss; tcp_parse_options(skb, &tmp_opt, 0, dst); @@ -1308,7 +1308,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) tcp_death_row.sysctl_tw_recycle && (peer = rt_get_peer((struct rtable *)dst)) != NULL && peer->v4daddr == saddr) { - if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL && + if (get_seconds() < peer->tcp_ts_stamp + TCP_PAWS_MSL && (s32)(peer->tcp_ts - req->ts_recent) > TCP_PAWS_WINDOW) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED); @@ -1727,9 +1727,9 @@ int tcp_v4_remember_stamp(struct sock *sk) if (peer) { if ((s32)(peer->tcp_ts - tp->rx_opt.ts_recent) <= 0 || - ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL && - peer->tcp_ts_stamp <= (u32)tp->rx_opt.ts_recent_stamp)) { - peer->tcp_ts_stamp = (u32)tp->rx_opt.ts_recent_stamp; + (peer->tcp_ts_stamp + TCP_PAWS_MSL < get_seconds() && + peer->tcp_ts_stamp <= tp->rx_opt.ts_recent_stamp)) { + peer->tcp_ts_stamp = tp->rx_opt.ts_recent_stamp; peer->tcp_ts = tp->rx_opt.ts_recent; } if (release_it) @@ -1748,9 +1748,9 @@ int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw) const struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 || - ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL && - peer->tcp_ts_stamp <= (u32)tcptw->tw_ts_recent_stamp)) { - peer->tcp_ts_stamp = (u32)tcptw->tw_ts_recent_stamp; + (peer->tcp_ts_stamp + TCP_PAWS_MSL < get_seconds() && + peer->tcp_ts_stamp <= tcptw->tw_ts_recent_stamp)) { + peer->tcp_ts_stamp = tcptw->tw_ts_recent_stamp; peer->tcp_ts = tcptw->tw_ts_recent; } inet_putpeer(peer); @@ -1815,7 +1815,7 @@ static int tcp_v4_init_sock(struct sock *sk) */ tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; tp->snd_cwnd_clamp = ~0; - tp->mss_cache = TCP_MSS_DEFAULT; + tp->mss_cache = 536; tp->reordering = sysctl_tcp_reordering; icsk->icsk_ca_ops = &tcp_init_congestion_ops; diff --git a/trunk/net/ipv4/tcp_minisocks.c b/trunk/net/ipv4/tcp_minisocks.c index 4be22280e6b3..a9d34e224cb6 100644 --- a/trunk/net/ipv4/tcp_minisocks.c +++ b/trunk/net/ipv4/tcp_minisocks.c @@ -476,7 +476,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, if (newtp->af_specific->md5_lookup(sk, newsk)) newtp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED; #endif - if (skb->len >= TCP_MSS_DEFAULT + newtp->tcp_header_len) + if (skb->len >= TCP_MIN_RCVMSS+newtp->tcp_header_len) newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; newtp->rx_opt.mss_clamp = req->mss; TCP_ECN_openreq_child(newtp, req); diff --git a/trunk/net/ipv4/udp.c b/trunk/net/ipv4/udp.c index 1eaf57567ebf..4274c1cc78fd 100644 --- a/trunk/net/ipv4/udp.c +++ b/trunk/net/ipv4/udp.c @@ -138,65 +138,31 @@ static int udp_lib_lport_inuse(struct net *net, __u16 num, sk_nulls_for_each(sk2, node, &hslot->head) if (net_eq(sock_net(sk2), net) && sk2 != sk && - (bitmap || udp_sk(sk2)->udp_port_hash == num) && + (bitmap || sk2->sk_hash == num) && (!sk2->sk_reuse || !sk->sk_reuse) && (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && (*saddr_comp)(sk, sk2)) { if (bitmap) - __set_bit(udp_sk(sk2)->udp_port_hash >> log, - bitmap); + __set_bit(sk2->sk_hash >> log, bitmap); else return 1; } return 0; } -/* - * Note: we still hold spinlock of primary hash chain, so no other writer - * can insert/delete a socket with local_port == num - */ -static int udp_lib_lport_inuse2(struct net *net, __u16 num, - struct udp_hslot *hslot2, - struct sock *sk, - int (*saddr_comp)(const struct sock *sk1, - const struct sock *sk2)) -{ - struct sock *sk2; - struct hlist_nulls_node *node; - int res = 0; - - spin_lock(&hslot2->lock); - udp_portaddr_for_each_entry(sk2, node, &hslot2->head) - if (net_eq(sock_net(sk2), net) && - sk2 != sk && - (udp_sk(sk2)->udp_port_hash == num) && - (!sk2->sk_reuse || !sk->sk_reuse) && - (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if - || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && - (*saddr_comp)(sk, sk2)) { - res = 1; - break; - } - spin_unlock(&hslot2->lock); - return res; -} - /** * udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6 * * @sk: socket struct in question * @snum: port number to look up * @saddr_comp: AF-dependent comparison of bound local IP addresses - * @hash2_nulladdr: AF-dependant hash value in secondary hash chains, - * with NULL address */ int udp_lib_get_port(struct sock *sk, unsigned short snum, int (*saddr_comp)(const struct sock *sk1, - const struct sock *sk2), - unsigned int hash2_nulladdr) + const struct sock *sk2)) { - struct udp_hslot *hslot, *hslot2; + struct udp_hslot *hslot; struct udp_table *udptable = sk->sk_prot->h.udp_table; int error = 1; struct net *net = sock_net(sk); @@ -243,49 +209,16 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, } else { hslot = udp_hashslot(udptable, net, snum); spin_lock_bh(&hslot->lock); - if (hslot->count > 10) { - int exist; - unsigned int slot2 = udp_sk(sk)->udp_portaddr_hash ^ snum; - - slot2 &= udptable->mask; - hash2_nulladdr &= udptable->mask; - - hslot2 = udp_hashslot2(udptable, slot2); - if (hslot->count < hslot2->count) - goto scan_primary_hash; - - exist = udp_lib_lport_inuse2(net, snum, hslot2, - sk, saddr_comp); - if (!exist && (hash2_nulladdr != slot2)) { - hslot2 = udp_hashslot2(udptable, hash2_nulladdr); - exist = udp_lib_lport_inuse2(net, snum, hslot2, - sk, saddr_comp); - } - if (exist) - goto fail_unlock; - else - goto found; - } -scan_primary_hash: if (udp_lib_lport_inuse(net, snum, hslot, NULL, sk, saddr_comp, 0)) goto fail_unlock; } found: inet_sk(sk)->inet_num = snum; - udp_sk(sk)->udp_port_hash = snum; - udp_sk(sk)->udp_portaddr_hash ^= snum; + sk->sk_hash = snum; if (sk_unhashed(sk)) { sk_nulls_add_node_rcu(sk, &hslot->head); - hslot->count++; sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); - - hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash); - spin_lock(&hslot2->lock); - hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node, - &hslot2->head); - hslot2->count++; - spin_unlock(&hslot2->lock); } error = 0; fail_unlock: @@ -304,22 +237,9 @@ static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) inet1->inet_rcv_saddr == inet2->inet_rcv_saddr)); } -static unsigned int udp4_portaddr_hash(struct net *net, __be32 saddr, - unsigned int port) -{ - return jhash_1word(saddr, net_hash_mix(net)) ^ port; -} - int udp_v4_get_port(struct sock *sk, unsigned short snum) { - unsigned int hash2_nulladdr = - udp4_portaddr_hash(sock_net(sk), INADDR_ANY, snum); - unsigned int hash2_partial = - udp4_portaddr_hash(sock_net(sk), inet_sk(sk)->inet_rcv_saddr, 0); - - /* precompute partial secondary hash */ - udp_sk(sk)->udp_portaddr_hash = hash2_partial; - return udp_lib_get_port(sk, snum, ipv4_rcv_saddr_equal, hash2_nulladdr); + return udp_lib_get_port(sk, snum, ipv4_rcv_saddr_equal); } static inline int compute_score(struct sock *sk, struct net *net, __be32 saddr, @@ -328,7 +248,7 @@ static inline int compute_score(struct sock *sk, struct net *net, __be32 saddr, { int score = -1; - if (net_eq(sock_net(sk), net) && udp_sk(sk)->udp_port_hash == hnum && + if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum && !ipv6_only_sock(sk)) { struct inet_sock *inet = inet_sk(sk); @@ -357,89 +277,6 @@ static inline int compute_score(struct sock *sk, struct net *net, __be32 saddr, return score; } -/* - * In this second variant, we check (daddr, dport) matches (inet_rcv_sadd, inet_num) - */ -#define SCORE2_MAX (1 + 2 + 2 + 2) -static inline int compute_score2(struct sock *sk, struct net *net, - __be32 saddr, __be16 sport, - __be32 daddr, unsigned int hnum, int dif) -{ - int score = -1; - - if (net_eq(sock_net(sk), net) && !ipv6_only_sock(sk)) { - struct inet_sock *inet = inet_sk(sk); - - if (inet->inet_rcv_saddr != daddr) - return -1; - if (inet->inet_num != hnum) - return -1; - - score = (sk->sk_family == PF_INET ? 1 : 0); - if (inet->inet_daddr) { - if (inet->inet_daddr != saddr) - return -1; - score += 2; - } - if (inet->inet_dport) { - if (inet->inet_dport != sport) - return -1; - score += 2; - } - if (sk->sk_bound_dev_if) { - if (sk->sk_bound_dev_if != dif) - return -1; - score += 2; - } - } - return score; -} - - -/* called with read_rcu_lock() */ -static struct sock *udp4_lib_lookup2(struct net *net, - __be32 saddr, __be16 sport, - __be32 daddr, unsigned int hnum, int dif, - struct udp_hslot *hslot2, unsigned int slot2) -{ - struct sock *sk, *result; - struct hlist_nulls_node *node; - int score, badness; - -begin: - result = NULL; - badness = -1; - udp_portaddr_for_each_entry_rcu(sk, node, &hslot2->head) { - score = compute_score2(sk, net, saddr, sport, - daddr, hnum, dif); - if (score > badness) { - result = sk; - badness = score; - if (score == SCORE2_MAX) - goto exact_match; - } - } - /* - * if the nulls value we got at the end of this lookup is - * not the expected one, we must restart lookup. - * We probably met an item that was moved to another chain. - */ - if (get_nulls_value(node) != slot2) - goto begin; - - if (result) { -exact_match: - if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt))) - result = NULL; - else if (unlikely(compute_score2(result, net, saddr, sport, - daddr, hnum, dif) < badness)) { - sock_put(result); - goto begin; - } - } - return result; -} - /* UDP is nearly always wildcards out the wazoo, it makes no sense to try * harder than this. -DaveM */ @@ -450,35 +287,11 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, struct sock *sk, *result; struct hlist_nulls_node *node; unsigned short hnum = ntohs(dport); - unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask); - struct udp_hslot *hslot2, *hslot = &udptable->hash[slot]; + unsigned int hash = udp_hashfn(net, hnum, udptable->mask); + struct udp_hslot *hslot = &udptable->hash[hash]; int score, badness; rcu_read_lock(); - if (hslot->count > 10) { - hash2 = udp4_portaddr_hash(net, daddr, hnum); - slot2 = hash2 & udptable->mask; - hslot2 = &udptable->hash2[slot2]; - if (hslot->count < hslot2->count) - goto begin; - - result = udp4_lib_lookup2(net, saddr, sport, - daddr, hnum, dif, - hslot2, slot2); - if (!result) { - hash2 = udp4_portaddr_hash(net, INADDR_ANY, hnum); - slot2 = hash2 & udptable->mask; - hslot2 = &udptable->hash2[slot2]; - if (hslot->count < hslot2->count) - goto begin; - - result = udp4_lib_lookup2(net, INADDR_ANY, sport, - daddr, hnum, dif, - hslot2, slot2); - } - rcu_read_unlock(); - return result; - } begin: result = NULL; badness = -1; @@ -495,7 +308,7 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, * not the expected one, we must restart lookup. * We probably met an item that was moved to another chain. */ - if (get_nulls_value(node) != slot) + if (get_nulls_value(node) != hash) goto begin; if (result) { @@ -546,7 +359,7 @@ static inline struct sock *udp_v4_mcast_next(struct net *net, struct sock *sk, struct inet_sock *inet = inet_sk(s); if (!net_eq(sock_net(s), net) || - udp_sk(s)->udp_port_hash != hnum || + s->sk_hash != hnum || (inet->inet_daddr && inet->inet_daddr != rmt_addr) || (inet->inet_dport != rmt_port && inet->inet_dport) || (inet->inet_rcv_saddr && @@ -1192,7 +1005,9 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, err = ulen; out_free: - skb_free_datagram_locked(sk, skb); + lock_sock(sk); + skb_free_datagram(sk, skb); + release_sock(sk); out: return err; @@ -1235,22 +1050,13 @@ void udp_lib_unhash(struct sock *sk) { if (sk_hashed(sk)) { struct udp_table *udptable = sk->sk_prot->h.udp_table; - struct udp_hslot *hslot, *hslot2; - - hslot = udp_hashslot(udptable, sock_net(sk), - udp_sk(sk)->udp_port_hash); - hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash); + struct udp_hslot *hslot = udp_hashslot(udptable, sock_net(sk), + sk->sk_hash); spin_lock_bh(&hslot->lock); if (sk_nulls_del_node_init_rcu(sk)) { - hslot->count--; inet_sk(sk)->inet_num = 0; sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); - - spin_lock(&hslot2->lock); - hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node); - hslot2->count--; - spin_unlock(&hslot2->lock); } spin_unlock_bh(&hslot->lock); } @@ -1386,83 +1192,49 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) return -1; } - -static void flush_stack(struct sock **stack, unsigned int count, - struct sk_buff *skb, unsigned int final) -{ - unsigned int i; - struct sk_buff *skb1 = NULL; - struct sock *sk; - - for (i = 0; i < count; i++) { - sk = stack[i]; - if (likely(skb1 == NULL)) - skb1 = (i == final) ? skb : skb_clone(skb, GFP_ATOMIC); - - if (!skb1) { - atomic_inc(&sk->sk_drops); - UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, - IS_UDPLITE(sk)); - UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, - IS_UDPLITE(sk)); - } - - if (skb1 && udp_queue_rcv_skb(sk, skb1) <= 0) - skb1 = NULL; - } - if (unlikely(skb1)) - kfree_skb(skb1); -} - /* * Multicasts and broadcasts go to each listener. * - * Note: called only from the BH handler context. + * Note: called only from the BH handler context, + * so we don't need to lock the hashes. */ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, struct udphdr *uh, __be32 saddr, __be32 daddr, struct udp_table *udptable) { - struct sock *sk, *stack[256 / sizeof(struct sock *)]; + struct sock *sk; struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest)); int dif; - unsigned int i, count = 0; spin_lock(&hslot->lock); sk = sk_nulls_head(&hslot->head); dif = skb->dev->ifindex; sk = udp_v4_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); - while (sk) { - stack[count++] = sk; - sk = udp_v4_mcast_next(net, sk_nulls_next(sk), uh->dest, - daddr, uh->source, saddr, dif); - if (unlikely(count == ARRAY_SIZE(stack))) { - if (!sk) - break; - flush_stack(stack, count, skb, ~0); - count = 0; - } - } - /* - * before releasing chain lock, we must take a reference on sockets - */ - for (i = 0; i < count; i++) - sock_hold(stack[i]); - + if (sk) { + struct sock *sknext = NULL; + + do { + struct sk_buff *skb1 = skb; + + sknext = udp_v4_mcast_next(net, sk_nulls_next(sk), uh->dest, + daddr, uh->source, saddr, + dif); + if (sknext) + skb1 = skb_clone(skb, GFP_ATOMIC); + + if (skb1) { + int ret = udp_queue_rcv_skb(sk, skb1); + if (ret > 0) + /* we should probably re-process instead + * of dropping packets here. */ + kfree_skb(skb1); + } + sk = sknext; + } while (sknext); + } else + consume_skb(skb); spin_unlock(&hslot->lock); - - /* - * do the slow work with no lock held - */ - if (count) { - flush_stack(stack, count, skb, count - 1); - - for (i = 0; i < count; i++) - sock_put(stack[i]); - } else { - kfree_skb(skb); - } return 0; } @@ -2072,7 +1844,7 @@ void __init udp_table_init(struct udp_table *table, const char *name) if (!CONFIG_BASE_SMALL) table->hash = alloc_large_system_hash(name, - 2 * sizeof(struct udp_hslot), + sizeof(struct udp_hslot), uhash_entries, 21, /* one slot per 2 MB */ 0, @@ -2084,23 +1856,16 @@ void __init udp_table_init(struct udp_table *table, const char *name) */ if (CONFIG_BASE_SMALL || table->mask < UDP_HTABLE_SIZE_MIN - 1) { table->hash = kmalloc(UDP_HTABLE_SIZE_MIN * - 2 * sizeof(struct udp_hslot), GFP_KERNEL); + sizeof(struct udp_hslot), GFP_KERNEL); if (!table->hash) panic(name); table->log = ilog2(UDP_HTABLE_SIZE_MIN); table->mask = UDP_HTABLE_SIZE_MIN - 1; } - table->hash2 = table->hash + (table->mask + 1); for (i = 0; i <= table->mask; i++) { INIT_HLIST_NULLS_HEAD(&table->hash[i].head, i); - table->hash[i].count = 0; spin_lock_init(&table->hash[i].lock); } - for (i = 0; i <= table->mask; i++) { - INIT_HLIST_NULLS_HEAD(&table->hash2[i].head, i); - table->hash2[i].count = 0; - spin_lock_init(&table->hash2[i].lock); - } } void __init udp_init(void) diff --git a/trunk/net/ipv4/udplite.c b/trunk/net/ipv4/udplite.c index 66f79513f4a5..470c504b9554 100644 --- a/trunk/net/ipv4/udplite.c +++ b/trunk/net/ipv4/udplite.c @@ -64,6 +64,7 @@ static struct inet_protosw udplite4_protosw = { .protocol = IPPROTO_UDPLITE, .prot = &udplite_prot, .ops = &inet_dgram_ops, + .capability = -1, .no_check = 0, /* must checksum (RFC 3828) */ .flags = INET_PROTOSW_PERMANENT, }; diff --git a/trunk/net/ipv6/addrconf.c b/trunk/net/ipv6/addrconf.c index 522bdc77206c..024bba30de21 100644 --- a/trunk/net/ipv6/addrconf.c +++ b/trunk/net/ipv6/addrconf.c @@ -3481,114 +3481,85 @@ enum addr_type_t ANYCAST_ADDR, }; -/* called with rcu_read_lock() */ -static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, - struct netlink_callback *cb, enum addr_type_t type, - int s_ip_idx, int *p_ip_idx) -{ - struct inet6_ifaddr *ifa; - struct ifmcaddr6 *ifmca; - struct ifacaddr6 *ifaca; - int err = 1; - int ip_idx = *p_ip_idx; - - read_lock_bh(&idev->lock); - switch (type) { - case UNICAST_ADDR: - /* unicast address incl. temp addr */ - for (ifa = idev->addr_list; ifa; - ifa = ifa->if_next, ip_idx++) { - if (ip_idx < s_ip_idx) - continue; - err = inet6_fill_ifaddr(skb, ifa, - NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, - RTM_NEWADDR, - NLM_F_MULTI); - if (err <= 0) - break; - } - break; - case MULTICAST_ADDR: - /* multicast address */ - for (ifmca = idev->mc_list; ifmca; - ifmca = ifmca->next, ip_idx++) { - if (ip_idx < s_ip_idx) - continue; - err = inet6_fill_ifmcaddr(skb, ifmca, - NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, - RTM_GETMULTICAST, - NLM_F_MULTI); - if (err <= 0) - break; - } - break; - case ANYCAST_ADDR: - /* anycast address */ - for (ifaca = idev->ac_list; ifaca; - ifaca = ifaca->aca_next, ip_idx++) { - if (ip_idx < s_ip_idx) - continue; - err = inet6_fill_ifacaddr(skb, ifaca, - NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, - RTM_GETANYCAST, - NLM_F_MULTI); - if (err <= 0) - break; - } - break; - default: - break; - } - read_unlock_bh(&idev->lock); - *p_ip_idx = ip_idx; - return err; -} - static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, enum addr_type_t type) { - struct net *net = sock_net(skb->sk); - int h, s_h; int idx, ip_idx; int s_idx, s_ip_idx; + int err = 1; struct net_device *dev; - struct inet6_dev *idev; - struct hlist_head *head; - struct hlist_node *node; + struct inet6_dev *idev = NULL; + struct inet6_ifaddr *ifa; + struct ifmcaddr6 *ifmca; + struct ifacaddr6 *ifaca; + struct net *net = sock_net(skb->sk); - s_h = cb->args[0]; - s_idx = idx = cb->args[1]; - s_ip_idx = ip_idx = cb->args[2]; + s_idx = cb->args[0]; + s_ip_idx = ip_idx = cb->args[1]; - rcu_read_lock(); - for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { - idx = 0; - head = &net->dev_index_head[h]; - hlist_for_each_entry_rcu(dev, node, head, index_hlist) { - if (idx < s_idx) - goto cont; - if (idx > s_idx) - s_ip_idx = 0; - ip_idx = 0; - if ((idev = __in6_dev_get(dev)) == NULL) - goto cont; - - if (in6_dump_addrs(idev, skb, cb, type, - s_ip_idx, &ip_idx) <= 0) - goto done; -cont: - idx++; + idx = 0; + for_each_netdev(net, dev) { + if (idx < s_idx) + goto cont; + if (idx > s_idx) + s_ip_idx = 0; + ip_idx = 0; + if ((idev = in6_dev_get(dev)) == NULL) + goto cont; + read_lock_bh(&idev->lock); + switch (type) { + case UNICAST_ADDR: + /* unicast address incl. temp addr */ + for (ifa = idev->addr_list; ifa; + ifa = ifa->if_next, ip_idx++) { + if (ip_idx < s_ip_idx) + continue; + err = inet6_fill_ifaddr(skb, ifa, + NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, + RTM_NEWADDR, + NLM_F_MULTI); + } + break; + case MULTICAST_ADDR: + /* multicast address */ + for (ifmca = idev->mc_list; ifmca; + ifmca = ifmca->next, ip_idx++) { + if (ip_idx < s_ip_idx) + continue; + err = inet6_fill_ifmcaddr(skb, ifmca, + NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, + RTM_GETMULTICAST, + NLM_F_MULTI); + } + break; + case ANYCAST_ADDR: + /* anycast address */ + for (ifaca = idev->ac_list; ifaca; + ifaca = ifaca->aca_next, ip_idx++) { + if (ip_idx < s_ip_idx) + continue; + err = inet6_fill_ifacaddr(skb, ifaca, + NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, + RTM_GETANYCAST, + NLM_F_MULTI); + } + break; + default: + break; } - } -done: - rcu_read_unlock(); - cb->args[0] = h; - cb->args[1] = idx; - cb->args[2] = ip_idx; + read_unlock_bh(&idev->lock); + in6_dev_put(idev); + if (err <= 0) + break; +cont: + idx++; + } + cb->args[0] = idx; + cb->args[1] = ip_idx; return skb->len; } @@ -3852,39 +3823,28 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) { struct net *net = sock_net(skb->sk); - int h, s_h; - int idx = 0, s_idx; + int idx, err; + int s_idx = cb->args[0]; struct net_device *dev; struct inet6_dev *idev; - struct hlist_head *head; - struct hlist_node *node; - - s_h = cb->args[0]; - s_idx = cb->args[1]; - rcu_read_lock(); - for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { - idx = 0; - head = &net->dev_index_head[h]; - hlist_for_each_entry_rcu(dev, node, head, index_hlist) { - if (idx < s_idx) - goto cont; - idev = __in6_dev_get(dev); - if (!idev) - goto cont; - if (inet6_fill_ifinfo(skb, idev, - NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, - RTM_NEWLINK, NLM_F_MULTI) <= 0) - goto out; + read_lock(&dev_base_lock); + idx = 0; + for_each_netdev(net, dev) { + if (idx < s_idx) + goto cont; + if ((idev = in6_dev_get(dev)) == NULL) + goto cont; + err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI); + in6_dev_put(idev); + if (err <= 0) + break; cont: - idx++; - } + idx++; } -out: - rcu_read_unlock(); - cb->args[1] = idx; - cb->args[0] = h; + read_unlock(&dev_base_lock); + cb->args[0] = idx; return skb->len; } diff --git a/trunk/net/ipv6/af_inet6.c b/trunk/net/ipv6/af_inet6.c index 12e69d364dd5..9105b25defe5 100644 --- a/trunk/net/ipv6/af_inet6.c +++ b/trunk/net/ipv6/af_inet6.c @@ -95,8 +95,7 @@ static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) return (struct ipv6_pinfo *)(((u8 *)sk) + offset); } -static int inet6_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int inet6_create(struct net *net, struct socket *sock, int protocol) { struct inet_sock *inet; struct ipv6_pinfo *np; @@ -159,7 +158,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol, } err = -EPERM; - if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) + if (answer->capability > 0 && !capable(answer->capability)) goto out_rcu_unlock; sock->ops = answer->ops; diff --git a/trunk/net/ipv6/anycast.c b/trunk/net/ipv6/anycast.c index f1c74c8ef9de..2f00ca83f049 100644 --- a/trunk/net/ipv6/anycast.c +++ b/trunk/net/ipv6/anycast.c @@ -431,9 +431,9 @@ static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq) struct net *net = seq_file_net(seq); state->idev = NULL; - for_each_netdev_rcu(net, state->dev) { + for_each_netdev(net, state->dev) { struct inet6_dev *idev; - idev = __in6_dev_get(state->dev); + idev = in6_dev_get(state->dev); if (!idev) continue; read_lock_bh(&idev->lock); @@ -443,6 +443,7 @@ static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq) break; } read_unlock_bh(&idev->lock); + in6_dev_put(idev); } return im; } @@ -453,15 +454,16 @@ static struct ifacaddr6 *ac6_get_next(struct seq_file *seq, struct ifacaddr6 *im im = im->aca_next; while (!im) { - if (likely(state->idev != NULL)) + if (likely(state->idev != NULL)) { read_unlock_bh(&state->idev->lock); - - state->dev = next_net_device_rcu(state->dev); + in6_dev_put(state->idev); + } + state->dev = next_net_device(state->dev); if (!state->dev) { state->idev = NULL; break; } - state->idev = __in6_dev_get(state->dev); + state->idev = in6_dev_get(state->dev); if (!state->idev) continue; read_lock_bh(&state->idev->lock); @@ -480,30 +482,29 @@ static struct ifacaddr6 *ac6_get_idx(struct seq_file *seq, loff_t pos) } static void *ac6_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(RCU) + __acquires(dev_base_lock) { - rcu_read_lock(); + read_lock(&dev_base_lock); return ac6_get_idx(seq, *pos); } static void *ac6_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - struct ifacaddr6 *im = ac6_get_next(seq, v); - + struct ifacaddr6 *im; + im = ac6_get_next(seq, v); ++*pos; return im; } static void ac6_seq_stop(struct seq_file *seq, void *v) - __releases(RCU) + __releases(dev_base_lock) { struct ac6_iter_state *state = ac6_seq_private(seq); - if (likely(state->idev != NULL)) { read_unlock_bh(&state->idev->lock); - state->idev = NULL; + in6_dev_put(state->idev); } - rcu_read_unlock(); + read_unlock(&dev_base_lock); } static int ac6_seq_show(struct seq_file *seq, void *v) diff --git a/trunk/net/ipv6/mcast.c b/trunk/net/ipv6/mcast.c index 1f9c44442e65..f9fcf690bd5d 100644 --- a/trunk/net/ipv6/mcast.c +++ b/trunk/net/ipv6/mcast.c @@ -2375,9 +2375,9 @@ static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq) struct net *net = seq_file_net(seq); state->idev = NULL; - for_each_netdev_rcu(net, state->dev) { + for_each_netdev(net, state->dev) { struct inet6_dev *idev; - idev = __in6_dev_get(state->dev); + idev = in6_dev_get(state->dev); if (!idev) continue; read_lock_bh(&idev->lock); @@ -2387,6 +2387,7 @@ static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq) break; } read_unlock_bh(&idev->lock); + in6_dev_put(idev); } return im; } @@ -2397,15 +2398,16 @@ static struct ifmcaddr6 *igmp6_mc_get_next(struct seq_file *seq, struct ifmcaddr im = im->next; while (!im) { - if (likely(state->idev != NULL)) + if (likely(state->idev != NULL)) { read_unlock_bh(&state->idev->lock); - - state->dev = next_net_device_rcu(state->dev); + in6_dev_put(state->idev); + } + state->dev = next_net_device(state->dev); if (!state->dev) { state->idev = NULL; break; } - state->idev = __in6_dev_get(state->dev); + state->idev = in6_dev_get(state->dev); if (!state->idev) continue; read_lock_bh(&state->idev->lock); @@ -2424,31 +2426,31 @@ static struct ifmcaddr6 *igmp6_mc_get_idx(struct seq_file *seq, loff_t pos) } static void *igmp6_mc_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(RCU) + __acquires(dev_base_lock) { - rcu_read_lock(); + read_lock(&dev_base_lock); return igmp6_mc_get_idx(seq, *pos); } static void *igmp6_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - struct ifmcaddr6 *im = igmp6_mc_get_next(seq, v); - + struct ifmcaddr6 *im; + im = igmp6_mc_get_next(seq, v); ++*pos; return im; } static void igmp6_mc_seq_stop(struct seq_file *seq, void *v) - __releases(RCU) + __releases(dev_base_lock) { struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); - if (likely(state->idev != NULL)) { read_unlock_bh(&state->idev->lock); + in6_dev_put(state->idev); state->idev = NULL; } state->dev = NULL; - rcu_read_unlock(); + read_unlock(&dev_base_lock); } static int igmp6_mc_seq_show(struct seq_file *seq, void *v) @@ -2505,9 +2507,9 @@ static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq) state->idev = NULL; state->im = NULL; - for_each_netdev_rcu(net, state->dev) { + for_each_netdev(net, state->dev) { struct inet6_dev *idev; - idev = __in6_dev_get(state->dev); + idev = in6_dev_get(state->dev); if (unlikely(idev == NULL)) continue; read_lock_bh(&idev->lock); @@ -2523,6 +2525,7 @@ static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq) spin_unlock_bh(&im->mca_lock); } read_unlock_bh(&idev->lock); + in6_dev_put(idev); } return psf; } @@ -2536,15 +2539,16 @@ static struct ip6_sf_list *igmp6_mcf_get_next(struct seq_file *seq, struct ip6_s spin_unlock_bh(&state->im->mca_lock); state->im = state->im->next; while (!state->im) { - if (likely(state->idev != NULL)) + if (likely(state->idev != NULL)) { read_unlock_bh(&state->idev->lock); - - state->dev = next_net_device_rcu(state->dev); + in6_dev_put(state->idev); + } + state->dev = next_net_device(state->dev); if (!state->dev) { state->idev = NULL; goto out; } - state->idev = __in6_dev_get(state->dev); + state->idev = in6_dev_get(state->dev); if (!state->idev) continue; read_lock_bh(&state->idev->lock); @@ -2569,9 +2573,9 @@ static struct ip6_sf_list *igmp6_mcf_get_idx(struct seq_file *seq, loff_t pos) } static void *igmp6_mcf_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(RCU) + __acquires(dev_base_lock) { - rcu_read_lock(); + read_lock(&dev_base_lock); return *pos ? igmp6_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } @@ -2587,7 +2591,7 @@ static void *igmp6_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void igmp6_mcf_seq_stop(struct seq_file *seq, void *v) - __releases(RCU) + __releases(dev_base_lock) { struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq); if (likely(state->im != NULL)) { @@ -2596,10 +2600,11 @@ static void igmp6_mcf_seq_stop(struct seq_file *seq, void *v) } if (likely(state->idev != NULL)) { read_unlock_bh(&state->idev->lock); + in6_dev_put(state->idev); state->idev = NULL; } state->dev = NULL; - rcu_read_unlock(); + read_unlock(&dev_base_lock); } static int igmp6_mcf_seq_show(struct seq_file *seq, void *v) diff --git a/trunk/net/ipv6/raw.c b/trunk/net/ipv6/raw.c index 926ce8eeffaf..cb834ab7f071 100644 --- a/trunk/net/ipv6/raw.c +++ b/trunk/net/ipv6/raw.c @@ -249,7 +249,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) /* Raw sockets are IPv6 only */ if (addr_type == IPV6_ADDR_MAPPED) - return -EADDRNOTAVAIL; + return(-EADDRNOTAVAIL); lock_sock(sk); @@ -257,7 +257,6 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (sk->sk_state != TCP_CLOSE) goto out; - rcu_read_lock(); /* Check if the address belongs to the host. */ if (addr_type != IPV6_ADDR_ANY) { struct net_device *dev = NULL; @@ -273,13 +272,13 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) /* Binding to link-local address requires an interface */ if (!sk->sk_bound_dev_if) - goto out_unlock; + goto out; - err = -ENODEV; - dev = dev_get_by_index_rcu(sock_net(sk), - sk->sk_bound_dev_if); - if (!dev) - goto out_unlock; + dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if); + if (!dev) { + err = -ENODEV; + goto out; + } } /* ipv4 addr of the socket is invalid. Only the @@ -290,9 +289,13 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) err = -EADDRNOTAVAIL; if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr, dev, 0)) { - goto out_unlock; + if (dev) + dev_put(dev); + goto out; } } + if (dev) + dev_put(dev); } inet->inet_rcv_saddr = inet->inet_saddr = v4addr; @@ -300,8 +303,6 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (!(addr_type & IPV6_ADDR_MULTICAST)) ipv6_addr_copy(&np->saddr, &addr->sin6_addr); err = 0; -out_unlock: - rcu_read_unlock(); out: release_sock(sk); return err; @@ -1335,6 +1336,7 @@ static struct inet_protosw rawv6_protosw = { .protocol = IPPROTO_IP, /* wild card */ .prot = &rawv6_prot, .ops = &inet6_sockraw_ops, + .capability = CAP_NET_RAW, .no_check = UDP_CSUM_DEFAULT, .flags = INET_PROTOSW_REUSE, }; diff --git a/trunk/net/ipv6/reassembly.c b/trunk/net/ipv6/reassembly.c index dce699fb2672..da5bd0ed83df 100644 --- a/trunk/net/ipv6/reassembly.c +++ b/trunk/net/ipv6/reassembly.c @@ -208,17 +208,18 @@ static void ip6_frag_expire(unsigned long data) fq_kill(fq); net = container_of(fq->q.net, struct net, ipv6.frags); - rcu_read_lock(); - dev = dev_get_by_index_rcu(net, fq->iif); + dev = dev_get_by_index(net, fq->iif); if (!dev) - goto out_rcu_unlock; + goto out; + rcu_read_lock(); IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); + rcu_read_unlock(); /* Don't send error if the first segment did not arrive. */ if (!(fq->q.last_in & INET_FRAG_FIRST_IN) || !fq->q.fragments) - goto out_rcu_unlock; + goto out; /* But use as source device on which LAST ARRIVED @@ -227,9 +228,9 @@ static void ip6_frag_expire(unsigned long data) */ fq->q.fragments->dev = dev; icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); -out_rcu_unlock: - rcu_read_unlock(); out: + if (dev) + dev_put(dev); spin_unlock(&fq->q.lock); fq_put(fq); } diff --git a/trunk/net/ipv6/sit.c b/trunk/net/ipv6/sit.c index b6e145a673ab..2362a3397e91 100644 --- a/trunk/net/ipv6/sit.c +++ b/trunk/net/ipv6/sit.c @@ -637,7 +637,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, struct iphdr *tiph = &tunnel->parms.iph; struct ipv6hdr *iph6 = ipv6_hdr(skb); u8 tos = tunnel->parms.iph.tos; - __be16 df = tiph->frag_off; struct rtable *rt; /* Route to the other host */ struct net_device *tdev; /* Device to other host */ struct iphdr *iph; /* Our new IP header */ @@ -727,28 +726,25 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, goto tx_error; } - if (df) { + if (tiph->frag_off) mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); + else + mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; - if (mtu < 68) { - stats->collisions++; - ip_rt_put(rt); - goto tx_error; - } - - if (mtu < IPV6_MIN_MTU) { - mtu = IPV6_MIN_MTU; - df = 0; - } - - if (tunnel->parms.iph.daddr && skb_dst(skb)) - skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); + if (mtu < 68) { + stats->collisions++; + ip_rt_put(rt); + goto tx_error; + } + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + if (tunnel->parms.iph.daddr && skb_dst(skb)) + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); - if (skb->len > mtu) { - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); - ip_rt_put(rt); - goto tx_error; - } + if (skb->len > mtu) { + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); + ip_rt_put(rt); + goto tx_error; } if (tunnel->err_count > 0) { @@ -796,7 +792,11 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, iph = ip_hdr(skb); iph->version = 4; iph->ihl = sizeof(struct iphdr)>>2; - iph->frag_off = df; + if (mtu > IPV6_MIN_MTU) + iph->frag_off = tiph->frag_off; + else + iph->frag_off = 0; + iph->protocol = IPPROTO_IPV6; iph->tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); iph->daddr = rt->rt_dst; diff --git a/trunk/net/ipv6/tcp_ipv6.c b/trunk/net/ipv6/tcp_ipv6.c index de709091b26d..34925f089e07 100644 --- a/trunk/net/ipv6/tcp_ipv6.c +++ b/trunk/net/ipv6/tcp_ipv6.c @@ -1851,7 +1851,7 @@ static int tcp_v6_init_sock(struct sock *sk) */ tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; tp->snd_cwnd_clamp = ~0; - tp->mss_cache = TCP_MSS_DEFAULT; + tp->mss_cache = 536; tp->reordering = sysctl_tcp_reordering; @@ -2112,6 +2112,7 @@ static struct inet_protosw tcpv6_protosw = { .protocol = IPPROTO_TCP, .prot = &tcpv6_prot, .ops = &inet6_stream_ops, + .capability = -1, .no_check = 0, .flags = INET_PROTOSW_PERMANENT | INET_PROTOSW_ICSK, diff --git a/trunk/net/ipv6/udp.c b/trunk/net/ipv6/udp.c index 69ebdbe78c47..d3b59d73f507 100644 --- a/trunk/net/ipv6/udp.c +++ b/trunk/net/ipv6/udp.c @@ -81,33 +81,9 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) return 0; } -static unsigned int udp6_portaddr_hash(struct net *net, - const struct in6_addr *addr6, - unsigned int port) -{ - unsigned int hash, mix = net_hash_mix(net); - - if (ipv6_addr_any(addr6)) - hash = jhash_1word(0, mix); - else if (ipv6_addr_v4mapped(addr6)) - hash = jhash_1word(addr6->s6_addr32[3], mix); - else - hash = jhash2(addr6->s6_addr32, 4, mix); - - return hash ^ port; -} - - int udp_v6_get_port(struct sock *sk, unsigned short snum) { - unsigned int hash2_nulladdr = - udp6_portaddr_hash(sock_net(sk), &in6addr_any, snum); - unsigned int hash2_partial = - udp6_portaddr_hash(sock_net(sk), &inet6_sk(sk)->rcv_saddr, 0); - - /* precompute partial secondary hash */ - udp_sk(sk)->udp_portaddr_hash = hash2_partial; - return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal, hash2_nulladdr); + return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal); } static inline int compute_score(struct sock *sk, struct net *net, @@ -118,7 +94,7 @@ static inline int compute_score(struct sock *sk, struct net *net, { int score = -1; - if (net_eq(sock_net(sk), net) && udp_sk(sk)->udp_port_hash == hnum && + if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum && sk->sk_family == PF_INET6) { struct ipv6_pinfo *np = inet6_sk(sk); struct inet_sock *inet = inet_sk(sk); @@ -148,86 +124,6 @@ static inline int compute_score(struct sock *sk, struct net *net, return score; } -#define SCORE2_MAX (1 + 1 + 1) -static inline int compute_score2(struct sock *sk, struct net *net, - const struct in6_addr *saddr, __be16 sport, - const struct in6_addr *daddr, unsigned short hnum, - int dif) -{ - int score = -1; - - if (net_eq(sock_net(sk), net) && udp_sk(sk)->udp_port_hash == hnum && - sk->sk_family == PF_INET6) { - struct ipv6_pinfo *np = inet6_sk(sk); - struct inet_sock *inet = inet_sk(sk); - - if (!ipv6_addr_equal(&np->rcv_saddr, daddr)) - return -1; - score = 0; - if (inet->inet_dport) { - if (inet->inet_dport != sport) - return -1; - score++; - } - if (!ipv6_addr_any(&np->daddr)) { - if (!ipv6_addr_equal(&np->daddr, saddr)) - return -1; - score++; - } - if (sk->sk_bound_dev_if) { - if (sk->sk_bound_dev_if != dif) - return -1; - score++; - } - } - return score; -} - - -/* called with read_rcu_lock() */ -static struct sock *udp6_lib_lookup2(struct net *net, - const struct in6_addr *saddr, __be16 sport, - const struct in6_addr *daddr, unsigned int hnum, int dif, - struct udp_hslot *hslot2, unsigned int slot2) -{ - struct sock *sk, *result; - struct hlist_nulls_node *node; - int score, badness; - -begin: - result = NULL; - badness = -1; - udp_portaddr_for_each_entry_rcu(sk, node, &hslot2->head) { - score = compute_score2(sk, net, saddr, sport, - daddr, hnum, dif); - if (score > badness) { - result = sk; - badness = score; - if (score == SCORE2_MAX) - goto exact_match; - } - } - /* - * if the nulls value we got at the end of this lookup is - * not the expected one, we must restart lookup. - * We probably met an item that was moved to another chain. - */ - if (get_nulls_value(node) != slot2) - goto begin; - - if (result) { -exact_match: - if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt))) - result = NULL; - else if (unlikely(compute_score2(result, net, saddr, sport, - daddr, hnum, dif) < badness)) { - sock_put(result); - goto begin; - } - } - return result; -} - static struct sock *__udp6_lib_lookup(struct net *net, struct in6_addr *saddr, __be16 sport, struct in6_addr *daddr, __be16 dport, @@ -236,35 +132,11 @@ static struct sock *__udp6_lib_lookup(struct net *net, struct sock *sk, *result; struct hlist_nulls_node *node; unsigned short hnum = ntohs(dport); - unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask); - struct udp_hslot *hslot2, *hslot = &udptable->hash[slot]; + unsigned int hash = udp_hashfn(net, hnum, udptable->mask); + struct udp_hslot *hslot = &udptable->hash[hash]; int score, badness; rcu_read_lock(); - if (hslot->count > 10) { - hash2 = udp6_portaddr_hash(net, daddr, hnum); - slot2 = hash2 & udptable->mask; - hslot2 = &udptable->hash2[slot2]; - if (hslot->count < hslot2->count) - goto begin; - - result = udp6_lib_lookup2(net, saddr, sport, - daddr, hnum, dif, - hslot2, slot2); - if (!result) { - hash2 = udp6_portaddr_hash(net, &in6addr_any, hnum); - slot2 = hash2 & udptable->mask; - hslot2 = &udptable->hash2[slot2]; - if (hslot->count < hslot2->count) - goto begin; - - result = udp6_lib_lookup2(net, &in6addr_any, sport, - daddr, hnum, dif, - hslot2, slot2); - } - rcu_read_unlock(); - return result; - } begin: result = NULL; badness = -1; @@ -280,7 +152,7 @@ static struct sock *__udp6_lib_lookup(struct net *net, * not the expected one, we must restart lookup. * We probably met an item that was moved to another chain. */ - if (get_nulls_value(node) != slot) + if (get_nulls_value(node) != hash) goto begin; if (result) { @@ -416,7 +288,9 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, err = ulen; out_free: - skb_free_datagram_locked(sk, skb); + lock_sock(sk); + skb_free_datagram(sk, skb); + release_sock(sk); out: return err; @@ -543,8 +417,7 @@ static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, if (!net_eq(sock_net(s), net)) continue; - if (udp_sk(s)->udp_port_hash == num && - s->sk_family == PF_INET6) { + if (s->sk_hash == num && s->sk_family == PF_INET6) { struct ipv6_pinfo *np = inet6_sk(s); if (inet->inet_dport) { if (inet->inet_dport != rmt_port) @@ -569,33 +442,6 @@ static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, return NULL; } -static void flush_stack(struct sock **stack, unsigned int count, - struct sk_buff *skb, unsigned int final) -{ - unsigned int i; - struct sock *sk; - struct sk_buff *skb1; - - for (i = 0; i < count; i++) { - skb1 = (i == final) ? skb : skb_clone(skb, GFP_ATOMIC); - - sk = stack[i]; - if (skb1) { - bh_lock_sock(sk); - if (!sock_owned_by_user(sk)) - udpv6_queue_rcv_skb(sk, skb1); - else - sk_add_backlog(sk, skb1); - bh_unlock_sock(sk); - } else { - atomic_inc(&sk->sk_drops); - UDP6_INC_STATS_BH(sock_net(sk), - UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk)); - UDP6_INC_STATS_BH(sock_net(sk), - UDP_MIB_INERRORS, IS_UDPLITE(sk)); - } - } -} /* * Note: called only from the BH handler context, * so we don't need to lock the hashes. @@ -604,43 +450,41 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, struct in6_addr *saddr, struct in6_addr *daddr, struct udp_table *udptable) { - struct sock *sk, *stack[256 / sizeof(struct sock *)]; + struct sock *sk, *sk2; const struct udphdr *uh = udp_hdr(skb); struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest)); int dif; - unsigned int i, count = 0; spin_lock(&hslot->lock); sk = sk_nulls_head(&hslot->head); dif = inet6_iif(skb); sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); - while (sk) { - stack[count++] = sk; - sk = udp_v6_mcast_next(net, sk_nulls_next(sk), uh->dest, daddr, - uh->source, saddr, dif); - if (unlikely(count == ARRAY_SIZE(stack))) { - if (!sk) - break; - flush_stack(stack, count, skb, ~0); - count = 0; - } + if (!sk) { + kfree_skb(skb); + goto out; } - /* - * before releasing the lock, we must take reference on sockets - */ - for (i = 0; i < count; i++) - sock_hold(stack[i]); - - spin_unlock(&hslot->lock); - - if (count) { - flush_stack(stack, count, skb, count - 1); - for (i = 0; i < count; i++) - sock_put(stack[i]); - } else { - kfree_skb(skb); + sk2 = sk; + while ((sk2 = udp_v6_mcast_next(net, sk_nulls_next(sk2), uh->dest, daddr, + uh->source, saddr, dif))) { + struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC); + if (buff) { + bh_lock_sock(sk2); + if (!sock_owned_by_user(sk2)) + udpv6_queue_rcv_skb(sk2, buff); + else + sk_add_backlog(sk2, buff); + bh_unlock_sock(sk2); + } } + bh_lock_sock(sk); + if (!sock_owned_by_user(sk)) + udpv6_queue_rcv_skb(sk, skb); + else + sk_add_backlog(sk, skb); + bh_unlock_sock(sk); +out: + spin_unlock(&hslot->lock); return 0; } @@ -1442,6 +1286,7 @@ static struct inet_protosw udpv6_protosw = { .protocol = IPPROTO_UDP, .prot = &udpv6_prot, .ops = &inet6_dgram_ops, + .capability =-1, .no_check = UDP_CSUM_DEFAULT, .flags = INET_PROTOSW_PERMANENT, }; diff --git a/trunk/net/ipv6/udplite.c b/trunk/net/ipv6/udplite.c index 6ea6938919e6..d737a27ee010 100644 --- a/trunk/net/ipv6/udplite.c +++ b/trunk/net/ipv6/udplite.c @@ -62,6 +62,7 @@ static struct inet_protosw udplite6_protosw = { .protocol = IPPROTO_UDPLITE, .prot = &udplitev6_prot, .ops = &inet6_dgram_ops, + .capability = -1, .no_check = 0, .flags = INET_PROTOSW_PERMANENT, }; diff --git a/trunk/net/ipx/af_ipx.c b/trunk/net/ipx/af_ipx.c index 975c5a366e55..6481ee4bdf72 100644 --- a/trunk/net/ipx/af_ipx.c +++ b/trunk/net/ipx/af_ipx.c @@ -1298,7 +1298,6 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname, int opt; int rc = -EINVAL; - lock_kernel(); if (optlen != sizeof(int)) goto out; @@ -1313,7 +1312,6 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname, ipx_sk(sk)->type = opt; rc = 0; out: - unlock_kernel(); return rc; } @@ -1325,7 +1323,6 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname, int len; int rc = -ENOPROTOOPT; - lock_kernel(); if (!(level == SOL_IPX && optname == IPX_TYPE)) goto out; @@ -1346,7 +1343,6 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname, rc = 0; out: - unlock_kernel(); return rc; } @@ -1356,8 +1352,7 @@ static struct proto ipx_proto = { .obj_size = sizeof(struct ipx_sock), }; -static int ipx_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int ipx_create(struct net *net, struct socket *sock, int protocol) { int rc = -ESOCKTNOSUPPORT; struct sock *sk; @@ -1395,7 +1390,6 @@ static int ipx_release(struct socket *sock) if (!sk) goto out; - lock_kernel(); if (!sock_flag(sk, SOCK_DEAD)) sk->sk_state_change(sk); @@ -1403,7 +1397,6 @@ static int ipx_release(struct socket *sock) sock->sk = NULL; sk_refcnt_debug_release(sk); ipx_destroy_socket(sk); - unlock_kernel(); out: return 0; } @@ -1431,8 +1424,7 @@ static __be16 ipx_first_free_socketnum(struct ipx_interface *intrfc) return htons(socketNum); } -static int __ipx_bind(struct socket *sock, - struct sockaddr *uaddr, int addr_len) +static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; struct ipx_sock *ipxs = ipx_sk(sk); @@ -1527,17 +1519,6 @@ static int __ipx_bind(struct socket *sock, return rc; } -static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) -{ - int rc; - - lock_kernel(); - rc = __ipx_bind(sock, uaddr, addr_len); - unlock_kernel(); - - return rc; -} - static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { @@ -1550,7 +1531,6 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, sk->sk_state = TCP_CLOSE; sock->state = SS_UNCONNECTED; - lock_kernel(); if (addr_len != sizeof(*addr)) goto out; addr = (struct sockaddr_ipx *)uaddr; @@ -1570,7 +1550,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, IPX_NODE_LEN); #endif /* CONFIG_IPX_INTERN */ - rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, + rc = ipx_bind(sock, (struct sockaddr *)&uaddr, sizeof(struct sockaddr_ipx)); if (rc) goto out; @@ -1597,7 +1577,6 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, ipxrtr_put(rt); rc = 0; out: - unlock_kernel(); return rc; } @@ -1613,7 +1592,6 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr, *uaddr_len = sizeof(struct sockaddr_ipx); - lock_kernel(); if (peer) { rc = -ENOTCONN; if (sk->sk_state != TCP_ESTABLISHED) @@ -1648,19 +1626,6 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr, rc = 0; out: - unlock_kernel(); - return rc; -} - -static unsigned int ipx_datagram_poll(struct file *file, struct socket *sock, - poll_table *wait) -{ - int rc; - - lock_kernel(); - rc = datagram_poll(file, sock, wait); - unlock_kernel(); - return rc; } @@ -1735,7 +1700,6 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock, int rc = -EINVAL; int flags = msg->msg_flags; - lock_kernel(); /* Socket gets bound below anyway */ /* if (sk->sk_zapped) return -EIO; */ /* Socket not bound */ @@ -1759,7 +1723,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock, memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, IPX_NODE_LEN); #endif - rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, + rc = ipx_bind(sock, (struct sockaddr *)&uaddr, sizeof(struct sockaddr_ipx)); if (rc) goto out; @@ -1787,7 +1751,6 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock, if (rc >= 0) rc = len; out: - unlock_kernel(); return rc; } @@ -1802,7 +1765,6 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb; int copied, rc; - lock_kernel(); /* put the autobinding in */ if (!ipxs->port) { struct sockaddr_ipx uaddr; @@ -1817,7 +1779,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, IPX_NODE_LEN); #endif /* CONFIG_IPX_INTERN */ - rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, + rc = ipx_bind(sock, (struct sockaddr *)&uaddr, sizeof(struct sockaddr_ipx)); if (rc) goto out; @@ -1861,7 +1823,6 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, out_free: skb_free_datagram(sk, skb); out: - unlock_kernel(); return rc; } @@ -1873,7 +1834,6 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) struct sock *sk = sock->sk; void __user *argp = (void __user *)arg; - lock_kernel(); switch (cmd) { case TIOCOUTQ: amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); @@ -1936,7 +1896,6 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) rc = -ENOIOCTLCMD; break; } - unlock_kernel(); return rc; } @@ -1974,7 +1933,7 @@ static const struct net_proto_family ipx_family_ops = { .owner = THIS_MODULE, }; -static const struct proto_ops ipx_dgram_ops = { +static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { .family = PF_IPX, .owner = THIS_MODULE, .release = ipx_release, @@ -1983,7 +1942,7 @@ static const struct proto_ops ipx_dgram_ops = { .socketpair = sock_no_socketpair, .accept = sock_no_accept, .getname = ipx_getname, - .poll = ipx_datagram_poll, + .poll = datagram_poll, .ioctl = ipx_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = ipx_compat_ioctl, @@ -1998,6 +1957,8 @@ static const struct proto_ops ipx_dgram_ops = { .sendpage = sock_no_sendpage, }; +SOCKOPS_WRAP(ipx_dgram, PF_IPX); + static struct packet_type ipx_8023_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_802_3), .func = ipx_rcv, diff --git a/trunk/net/irda/af_irda.c b/trunk/net/irda/af_irda.c index 10093aab6173..9429e4002bca 100644 --- a/trunk/net/irda/af_irda.c +++ b/trunk/net/irda/af_irda.c @@ -61,7 +61,7 @@ #include -static int irda_create(struct net *net, struct socket *sock, int protocol, int kern); +static int irda_create(struct net *net, struct socket *sock, int protocol); static const struct proto_ops irda_stream_ops; static const struct proto_ops irda_seqpacket_ops; @@ -714,14 +714,11 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, struct sockaddr_irda saddr; struct sock *sk = sock->sk; struct irda_sock *self = irda_sk(sk); - int err; - lock_kernel(); memset(&saddr, 0, sizeof(saddr)); if (peer) { - err = -ENOTCONN; if (sk->sk_state != TCP_ESTABLISHED) - goto out; + return -ENOTCONN; saddr.sir_family = AF_IRDA; saddr.sir_lsap_sel = self->dtsap_sel; @@ -738,10 +735,8 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, /* uaddr_len come to us uninitialised */ *uaddr_len = sizeof (struct sockaddr_irda); memcpy(uaddr, &saddr, *uaddr_len); - err = 0; -out: - unlock_kernel(); - return err; + + return 0; } /* @@ -753,25 +748,21 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, static int irda_listen(struct socket *sock, int backlog) { struct sock *sk = sock->sk; - int err = -EOPNOTSUPP; IRDA_DEBUG(2, "%s()\n", __func__); - lock_kernel(); if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) && (sk->sk_type != SOCK_DGRAM)) - goto out; + return -EOPNOTSUPP; if (sk->sk_state != TCP_LISTEN) { sk->sk_max_ack_backlog = backlog; sk->sk_state = TCP_LISTEN; - err = 0; + return 0; } -out: - unlock_kernel(); - return err; + return -EOPNOTSUPP; } /* @@ -792,40 +783,36 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (addr_len != sizeof(struct sockaddr_irda)) return -EINVAL; - lock_kernel(); #ifdef CONFIG_IRDA_ULTRA /* Special care for Ultra sockets */ if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA)) { self->pid = addr->sir_lsap_sel; - err = -EOPNOTSUPP; if (self->pid & 0x80) { IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__); - goto out; + return -EOPNOTSUPP; } err = irda_open_lsap(self, self->pid); if (err < 0) - goto out; + return err; /* Pretend we are connected */ sock->state = SS_CONNECTED; sk->sk_state = TCP_ESTABLISHED; - err = 0; - goto out; + return 0; } #endif /* CONFIG_IRDA_ULTRA */ self->ias_obj = irias_new_object(addr->sir_name, jiffies); - err = -ENOMEM; if (self->ias_obj == NULL) - goto out; + return -ENOMEM; err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name); if (err < 0) { kfree(self->ias_obj->name); kfree(self->ias_obj); - goto out; + return err; } /* Register with LM-IAS */ @@ -833,10 +820,7 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) self->stsap_sel, IAS_KERNEL_ATTR); irias_insert_object(self->ias_obj); - err = 0; -out: - unlock_kernel(); - return err; + return 0; } /* @@ -855,26 +839,22 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) IRDA_DEBUG(2, "%s()\n", __func__); - lock_kernel(); - err = irda_create(sock_net(sk), newsock, sk->sk_protocol, 0); + err = irda_create(sock_net(sk), newsock, sk->sk_protocol); if (err) - goto out; + return err; - err = -EINVAL; if (sock->state != SS_UNCONNECTED) - goto out; + return -EINVAL; if ((sk = sock->sk) == NULL) - goto out; + return -EINVAL; - err = -EOPNOTSUPP; if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) && (sk->sk_type != SOCK_DGRAM)) - goto out; + return -EOPNOTSUPP; - err = -EINVAL; if (sk->sk_state != TCP_LISTEN) - goto out; + return -EINVAL; /* * The read queue this time is holding sockets ready to use @@ -895,20 +875,18 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) break; /* Non blocking operation */ - err = -EWOULDBLOCK; if (flags & O_NONBLOCK) - goto out; + return -EWOULDBLOCK; err = wait_event_interruptible(*(sk->sk_sleep), skb_peek(&sk->sk_receive_queue)); if (err) - goto out; + return err; } newsk = newsock->sk; - err = -EIO; if (newsk == NULL) - goto out; + return -EIO; newsk->sk_state = TCP_ESTABLISHED; @@ -916,11 +894,10 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) /* Now attach up the new socket */ new->tsap = irttp_dup(self->tsap, new); - err = -EPERM; /* value does not seem to make sense. -arnd */ if (!new->tsap) { IRDA_DEBUG(0, "%s(), dup failed!\n", __func__); kfree_skb(skb); - goto out; + return -1; } new->stsap_sel = new->tsap->stsap_sel; @@ -944,10 +921,8 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) newsock->state = SS_CONNECTED; irda_connect_response(new); - err = 0; -out: - unlock_kernel(); - return err; + + return 0; } /* @@ -980,34 +955,28 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, IRDA_DEBUG(2, "%s(%p)\n", __func__, self); - lock_kernel(); /* Don't allow connect for Ultra sockets */ - err = -ESOCKTNOSUPPORT; if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA)) - goto out; + return -ESOCKTNOSUPPORT; if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { sock->state = SS_CONNECTED; - err = 0; - goto out; /* Connect completed during a ERESTARTSYS event */ + return 0; /* Connect completed during a ERESTARTSYS event */ } if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) { sock->state = SS_UNCONNECTED; - err = -ECONNREFUSED; - goto out; + return -ECONNREFUSED; } - err = -EISCONN; /* No reconnect on a seqpacket socket */ if (sk->sk_state == TCP_ESTABLISHED) - goto out; + return -EISCONN; /* No reconnect on a seqpacket socket */ sk->sk_state = TCP_CLOSE; sock->state = SS_UNCONNECTED; - err = -EINVAL; if (addr_len != sizeof(struct sockaddr_irda)) - goto out; + return -EINVAL; /* Check if user supplied any destination device address */ if ((!addr->sir_addr) || (addr->sir_addr == DEV_ADDR_ANY)) { @@ -1015,7 +984,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name); if (err) { IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __func__); - goto out; + return err; } } else { /* Use the one provided by the user */ @@ -1031,7 +1000,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, err = irda_find_lsap_sel(self, addr->sir_name); if (err) { IRDA_DEBUG(0, "%s(), connect failed!\n", __func__); - goto out; + return err; } } else { /* Directly connect to the remote LSAP @@ -1056,35 +1025,29 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, self->max_sdu_size_rx, NULL); if (err) { IRDA_DEBUG(0, "%s(), connect failed!\n", __func__); - goto out; + return err; } /* Now the loop */ - err = -EINPROGRESS; if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) - goto out; + return -EINPROGRESS; - err = -ERESTARTSYS; if (wait_event_interruptible(*(sk->sk_sleep), (sk->sk_state != TCP_SYN_SENT))) - goto out; + return -ERESTARTSYS; if (sk->sk_state != TCP_ESTABLISHED) { sock->state = SS_UNCONNECTED; err = sock_error(sk); - if (!err) - err = -ECONNRESET; - goto out; + return err? err : -ECONNRESET; } sock->state = SS_CONNECTED; /* At this point, IrLMP has assigned our source address */ self->saddr = irttp_get_saddr(self->tsap); - err = 0; -out: - unlock_kernel(); - return err; + + return 0; } static struct proto irda_proto = { @@ -1099,8 +1062,7 @@ static struct proto irda_proto = { * Create IrDA socket * */ -static int irda_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int irda_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; struct irda_sock *self; @@ -1230,7 +1192,6 @@ static int irda_release(struct socket *sock) if (sk == NULL) return 0; - lock_kernel(); lock_sock(sk); sk->sk_state = TCP_CLOSE; sk->sk_shutdown |= SEND_SHUTDOWN; @@ -1249,7 +1210,6 @@ static int irda_release(struct socket *sock) /* Destroy networking socket if we are the last reference on it, * i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */ sock_put(sk); - unlock_kernel(); /* Notes on socket locking and deallocation... - Jean II * In theory we should put pairs of sock_hold() / sock_put() to @@ -1297,37 +1257,28 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); - lock_kernel(); /* Note : socket.c set MSG_EOR on SEQPACKET sockets */ if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT | - MSG_NOSIGNAL)) { - err = -EINVAL; - goto out; - } + MSG_NOSIGNAL)) + return -EINVAL; if (sk->sk_shutdown & SEND_SHUTDOWN) goto out_err; - if (sk->sk_state != TCP_ESTABLISHED) { - err = -ENOTCONN; - goto out; - } + if (sk->sk_state != TCP_ESTABLISHED) + return -ENOTCONN; self = irda_sk(sk); /* Check if IrTTP is wants us to slow down */ if (wait_event_interruptible(*(sk->sk_sleep), - (self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED))) { - err = -ERESTARTSYS; - goto out; - } + (self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED))) + return -ERESTARTSYS; /* Check if we are still connected */ - if (sk->sk_state != TCP_ESTABLISHED) { - err = -ENOTCONN; - goto out; - } + if (sk->sk_state != TCP_ESTABLISHED) + return -ENOTCONN; /* Check that we don't send out too big frames */ if (len > self->max_data_size) { @@ -1359,16 +1310,11 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); goto out_err; } - - unlock_kernel(); /* Tell client how much data we actually sent */ return len; -out_err: - err = sk_stream_error(sk, msg->msg_flags, err); -out: - unlock_kernel(); - return err; + out_err: + return sk_stream_error(sk, msg->msg_flags, err); } @@ -1389,14 +1335,13 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, IRDA_DEBUG(4, "%s()\n", __func__); - lock_kernel(); if ((err = sock_error(sk)) < 0) - goto out; + return err; skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &err); if (!skb) - goto out; + return err; skb_reset_transport_header(skb); copied = skb->len; @@ -1424,12 +1369,8 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, irttp_flow_request(self->tsap, FLOW_START); } } - unlock_kernel(); - return copied; -out: - unlock_kernel(); - return err; + return copied; } /* @@ -1447,19 +1388,15 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, IRDA_DEBUG(3, "%s()\n", __func__); - lock_kernel(); if ((err = sock_error(sk)) < 0) - goto out; + return err; - err = -EINVAL; if (sock->flags & __SO_ACCEPTCON) - goto out; + return(-EINVAL); - err =-EOPNOTSUPP; if (flags & MSG_OOB) - goto out; + return -EOPNOTSUPP; - err = 0; target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); timeo = sock_rcvtimeo(sk, noblock); @@ -1471,7 +1408,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, if (skb == NULL) { DEFINE_WAIT(wait); - err = 0; + int ret = 0; if (copied >= target) break; @@ -1481,25 +1418,25 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, /* * POSIX 1003.1g mandates this order. */ - err = sock_error(sk); - if (err) + ret = sock_error(sk); + if (ret) ; else if (sk->sk_shutdown & RCV_SHUTDOWN) ; else if (noblock) - err = -EAGAIN; + ret = -EAGAIN; else if (signal_pending(current)) - err = sock_intr_errno(timeo); + ret = sock_intr_errno(timeo); else if (sk->sk_state != TCP_ESTABLISHED) - err = -ENOTCONN; + ret = -ENOTCONN; else if (skb_peek(&sk->sk_receive_queue) == NULL) /* Wait process until data arrives */ schedule(); finish_wait(sk->sk_sleep, &wait); - if (err) - goto out; + if (ret) + return ret; if (sk->sk_shutdown & RCV_SHUTDOWN) break; @@ -1552,9 +1489,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, } } -out: - unlock_kernel(); - return err ? : copied; + return copied; } /* @@ -1572,23 +1507,18 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb; int err; - lock_kernel(); - IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); - err = -EINVAL; if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) - goto out; + return -EINVAL; if (sk->sk_shutdown & SEND_SHUTDOWN) { send_sig(SIGPIPE, current, 0); - err = -EPIPE; - goto out; + return -EPIPE; } - err = -ENOTCONN; if (sk->sk_state != TCP_ESTABLISHED) - goto out; + return -ENOTCONN; self = irda_sk(sk); @@ -1605,9 +1535,8 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, skb = sock_alloc_send_skb(sk, len + self->max_header_size, msg->msg_flags & MSG_DONTWAIT, &err); - err = -ENOBUFS; if (!skb) - goto out; + return -ENOBUFS; skb_reserve(skb, self->max_header_size); skb_reset_transport_header(skb); @@ -1617,7 +1546,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len); if (err) { kfree_skb(skb); - goto out; + return err; } /* @@ -1627,13 +1556,9 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, err = irttp_udata_request(self->tsap, skb); if (err) { IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); - goto out; + return err; } - unlock_kernel(); return len; -out: - unlock_kernel(); - return err; } /* @@ -1655,15 +1580,12 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); - lock_kernel(); - err = -EINVAL; if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) - goto out; + return -EINVAL; - err = -EPIPE; if (sk->sk_shutdown & SEND_SHUTDOWN) { send_sig(SIGPIPE, current, 0); - goto out; + return -EPIPE; } self = irda_sk(sk); @@ -1671,18 +1593,16 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, /* Check if an address was specified with sendto. Jean II */ if (msg->msg_name) { struct sockaddr_irda *addr = (struct sockaddr_irda *) msg->msg_name; - err = -EINVAL; /* Check address, extract pid. Jean II */ if (msg->msg_namelen < sizeof(*addr)) - goto out; + return -EINVAL; if (addr->sir_family != AF_IRDA) - goto out; + return -EINVAL; pid = addr->sir_lsap_sel; if (pid & 0x80) { IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__); - err = -EOPNOTSUPP; - goto out; + return -EOPNOTSUPP; } } else { /* Check that the socket is properly bound to an Ultra @@ -1691,8 +1611,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, (sk->sk_state != TCP_ESTABLISHED)) { IRDA_DEBUG(0, "%s(), socket not bound to Ultra PID.\n", __func__); - err = -ENOTCONN; - goto out; + return -ENOTCONN; } /* Use PID from socket */ bound = 1; @@ -1711,9 +1630,8 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, skb = sock_alloc_send_skb(sk, len + self->max_header_size, msg->msg_flags & MSG_DONTWAIT, &err); - err = -ENOBUFS; if (!skb) - goto out; + return -ENOBUFS; skb_reserve(skb, self->max_header_size); skb_reset_transport_header(skb); @@ -1723,16 +1641,16 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len); if (err) { kfree_skb(skb); - goto out; + return err; } err = irlmp_connless_data_request((bound ? self->lsap : NULL), skb, pid); - if (err) + if (err) { IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); -out: - unlock_kernel(); - return err ? : len; + return err; + } + return len; } #endif /* CONFIG_IRDA_ULTRA */ @@ -1746,8 +1664,6 @@ static int irda_shutdown(struct socket *sock, int how) IRDA_DEBUG(1, "%s(%p)\n", __func__, self); - lock_kernel(); - sk->sk_state = TCP_CLOSE; sk->sk_shutdown |= SEND_SHUTDOWN; sk->sk_state_change(sk); @@ -1768,8 +1684,6 @@ static int irda_shutdown(struct socket *sock, int how) self->daddr = DEV_ADDR_ANY; /* Until we get re-connected */ self->saddr = 0x0; /* so IrLMP assign us any link */ - unlock_kernel(); - return 0; } @@ -1785,7 +1699,6 @@ static unsigned int irda_poll(struct file * file, struct socket *sock, IRDA_DEBUG(4, "%s()\n", __func__); - lock_kernel(); poll_wait(file, sk->sk_sleep, wait); mask = 0; @@ -1833,34 +1746,18 @@ static unsigned int irda_poll(struct file * file, struct socket *sock, default: break; } - unlock_kernel(); return mask; } -static unsigned int irda_datagram_poll(struct file *file, struct socket *sock, - poll_table *wait) -{ - int err; - - lock_kernel(); - err = datagram_poll(file, sock, wait); - unlock_kernel(); - - return err; -} - /* * Function irda_ioctl (sock, cmd, arg) */ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; - int err; IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd); - lock_kernel(); - err = -EINVAL; switch (cmd) { case TIOCOUTQ: { long amount; @@ -1868,8 +1765,9 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); if (amount < 0) amount = 0; - err = put_user(amount, (unsigned int __user *)arg); - break; + if (put_user(amount, (unsigned int __user *)arg)) + return -EFAULT; + return 0; } case TIOCINQ: { @@ -1878,14 +1776,15 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) /* These two are safe on a single CPU system as only user tasks fiddle here */ if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) amount = skb->len; - err = put_user(amount, (unsigned int __user *)arg); - break; + if (put_user(amount, (unsigned int __user *)arg)) + return -EFAULT; + return 0; } case SIOCGSTAMP: if (sk != NULL) - err = sock_get_timestamp(sk, (struct timeval __user *)arg); - break; + return sock_get_timestamp(sk, (struct timeval __user *)arg); + return -EINVAL; case SIOCGIFADDR: case SIOCSIFADDR: @@ -1897,14 +1796,14 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCSIFNETMASK: case SIOCGIFMETRIC: case SIOCSIFMETRIC: - break; + return -EINVAL; default: IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__); - err = -ENOIOCTLCMD; + return -ENOIOCTLCMD; } - unlock_kernel(); - return err; + /*NOTREACHED*/ + return 0; } #ifdef CONFIG_COMPAT @@ -1926,7 +1825,7 @@ static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned lon * Set some options for the socket * */ -static int __irda_setsockopt(struct socket *sock, int level, int optname, +static int irda_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { struct sock *sk = sock->sk; @@ -2184,18 +2083,6 @@ static int __irda_setsockopt(struct socket *sock, int level, int optname, return 0; } -static int irda_setsockopt(struct socket *sock, int level, int optname, - char __user *optval, unsigned int optlen) -{ - int err; - - lock_kernel(); - err = __irda_setsockopt(sock, level, optname, optval, optlen); - unlock_kernel(); - - return err; -} - /* * Function irda_extract_ias_value(ias_opt, ias_value) * @@ -2248,7 +2135,7 @@ static int irda_extract_ias_value(struct irda_ias_set *ias_opt, /* * Function irda_getsockopt (sock, level, optname, optval, optlen) */ -static int __irda_getsockopt(struct socket *sock, int level, int optname, +static int irda_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { struct sock *sk = sock->sk; @@ -2576,25 +2463,13 @@ static int __irda_getsockopt(struct socket *sock, int level, int optname, return 0; } -static int irda_getsockopt(struct socket *sock, int level, int optname, - char __user *optval, int __user *optlen) -{ - int err; - - lock_kernel(); - err = __irda_getsockopt(sock, level, optname, optval, optlen); - unlock_kernel(); - - return err; -} - static const struct net_proto_family irda_family_ops = { .family = PF_IRDA, .create = irda_create, .owner = THIS_MODULE, }; -static const struct proto_ops irda_stream_ops = { +static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = { .family = PF_IRDA, .owner = THIS_MODULE, .release = irda_release, @@ -2618,7 +2493,7 @@ static const struct proto_ops irda_stream_ops = { .sendpage = sock_no_sendpage, }; -static const struct proto_ops irda_seqpacket_ops = { +static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = { .family = PF_IRDA, .owner = THIS_MODULE, .release = irda_release, @@ -2627,7 +2502,7 @@ static const struct proto_ops irda_seqpacket_ops = { .socketpair = sock_no_socketpair, .accept = irda_accept, .getname = irda_getname, - .poll = irda_datagram_poll, + .poll = datagram_poll, .ioctl = irda_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = irda_compat_ioctl, @@ -2642,7 +2517,7 @@ static const struct proto_ops irda_seqpacket_ops = { .sendpage = sock_no_sendpage, }; -static const struct proto_ops irda_dgram_ops = { +static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = { .family = PF_IRDA, .owner = THIS_MODULE, .release = irda_release, @@ -2651,7 +2526,7 @@ static const struct proto_ops irda_dgram_ops = { .socketpair = sock_no_socketpair, .accept = irda_accept, .getname = irda_getname, - .poll = irda_datagram_poll, + .poll = datagram_poll, .ioctl = irda_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = irda_compat_ioctl, @@ -2667,7 +2542,7 @@ static const struct proto_ops irda_dgram_ops = { }; #ifdef CONFIG_IRDA_ULTRA -static const struct proto_ops irda_ultra_ops = { +static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = { .family = PF_IRDA, .owner = THIS_MODULE, .release = irda_release, @@ -2676,7 +2551,7 @@ static const struct proto_ops irda_ultra_ops = { .socketpair = sock_no_socketpair, .accept = sock_no_accept, .getname = irda_getname, - .poll = irda_datagram_poll, + .poll = datagram_poll, .ioctl = irda_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = irda_compat_ioctl, @@ -2692,6 +2567,13 @@ static const struct proto_ops irda_ultra_ops = { }; #endif /* CONFIG_IRDA_ULTRA */ +SOCKOPS_WRAP(irda_stream, PF_IRDA); +SOCKOPS_WRAP(irda_seqpacket, PF_IRDA); +SOCKOPS_WRAP(irda_dgram, PF_IRDA); +#ifdef CONFIG_IRDA_ULTRA +SOCKOPS_WRAP(irda_ultra, PF_IRDA); +#endif /* CONFIG_IRDA_ULTRA */ + /* * Function irsock_init (pro) * diff --git a/trunk/net/iucv/af_iucv.c b/trunk/net/iucv/af_iucv.c index 1e428863574f..3aebabb158a8 100644 --- a/trunk/net/iucv/af_iucv.c +++ b/trunk/net/iucv/af_iucv.c @@ -481,8 +481,7 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio) } /* Create an IUCV socket */ -static int iucv_sock_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int iucv_sock_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; diff --git a/trunk/net/iucv/iucv.c b/trunk/net/iucv/iucv.c index 3b1f5f5f8de7..3973d0e61e56 100644 --- a/trunk/net/iucv/iucv.c +++ b/trunk/net/iucv/iucv.c @@ -1768,6 +1768,7 @@ static void iucv_tasklet_fn(unsigned long ignored) */ static void iucv_work_fn(struct work_struct *work) { + typedef void iucv_irq_fn(struct iucv_irq_data *); LIST_HEAD(work_queue); struct iucv_irq_list *p, *n; @@ -1877,25 +1878,14 @@ int iucv_path_table_empty(void) static int iucv_pm_freeze(struct device *dev) { int cpu; - struct iucv_irq_list *p, *n; int rc = 0; #ifdef CONFIG_PM_DEBUG printk(KERN_WARNING "iucv_pm_freeze\n"); #endif - if (iucv_pm_state != IUCV_PM_FREEZING) { - for_each_cpu_mask_nr(cpu, iucv_irq_cpumask) - smp_call_function_single(cpu, iucv_block_cpu_almost, - NULL, 1); - cancel_work_sync(&iucv_work); - list_for_each_entry_safe(p, n, &iucv_work_queue, list) { - list_del_init(&p->list); - iucv_sever_pathid(p->data.ippathid, - iucv_error_no_listener); - kfree(p); - } - } iucv_pm_state = IUCV_PM_FREEZING; + for_each_cpu_mask_nr(cpu, iucv_irq_cpumask) + smp_call_function_single(cpu, iucv_block_cpu_almost, NULL, 1); if (dev->driver && dev->driver->pm && dev->driver->pm->freeze) rc = dev->driver->pm->freeze(dev); if (iucv_path_table_empty()) diff --git a/trunk/net/key/af_key.c b/trunk/net/key/af_key.c index 86b2c22d0918..472f6594184a 100644 --- a/trunk/net/key/af_key.c +++ b/trunk/net/key/af_key.c @@ -177,8 +177,7 @@ static struct proto key_proto = { .obj_size = sizeof(struct pfkey_sock), }; -static int pfkey_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int pfkey_create(struct net *net, struct socket *sock, int protocol) { struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); struct sock *sk; diff --git a/trunk/net/llc/af_llc.c b/trunk/net/llc/af_llc.c index 5266c286b260..4866b4fb0c27 100644 --- a/trunk/net/llc/af_llc.c +++ b/trunk/net/llc/af_llc.c @@ -140,17 +140,14 @@ static struct proto llc_proto = { /** * llc_ui_create - alloc and init a new llc_ui socket - * @net: network namespace (must be default network) * @sock: Socket to initialize and attach allocated sk to. * @protocol: Unused. - * @kern: on behalf of kernel or userspace * * Allocate and initialize a new llc_ui socket, validate the user wants a * socket type we have available. * Returns 0 upon success, negative upon failure. */ -static int llc_ui_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int llc_ui_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; int rc = -ESOCKTNOSUPPORT; diff --git a/trunk/net/mac80211/agg-tx.c b/trunk/net/mac80211/agg-tx.c index b09948ceec4a..bd765f30dba2 100644 --- a/trunk/net/mac80211/agg-tx.c +++ b/trunk/net/mac80211/agg-tx.c @@ -666,25 +666,26 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, state = &sta->ampdu_mlme.tid_state_tx[tid]; - del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); - spin_lock_bh(&sta->lock); - if (!(*state & HT_ADDBA_REQUESTED_MSK)) - goto timer_still_needed; + if (!(*state & HT_ADDBA_REQUESTED_MSK)) { + spin_unlock_bh(&sta->lock); + return; + } if (mgmt->u.action.u.addba_resp.dialog_token != sta->ampdu_mlme.tid_tx[tid]->dialog_token) { + spin_unlock_bh(&sta->lock); #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ - goto timer_still_needed; + return; } + del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ - if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) == WLAN_STATUS_SUCCESS) { u8 curstate = *state; @@ -698,11 +699,5 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, } else { ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); } - - goto out; - - timer_still_needed: - add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); - out: spin_unlock_bh(&sta->lock); } diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index 56319b51d170..5608f6c68413 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -72,9 +72,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, struct ieee80211_sub_if_data *sdata; int ret; - if (netif_running(dev)) - return -EBUSY; - if (!nl80211_type_check(type)) return -EINVAL; @@ -84,6 +81,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy, if (ret) return ret; + if (netif_running(sdata->dev)) + return -EBUSY; + if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) ieee80211_sdata_set_mesh_id(sdata, params->mesh_id_len, @@ -738,6 +738,13 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, err = sta_info_insert(sta); if (err) { + /* STA has been freed */ + if (err == -EEXIST && layer2_update) { + /* Need to update layer 2 devices on reassociation */ + sta = sta_info_get(local, mac); + if (sta) + ieee80211_send_layer2_update(sta); + } rcu_read_unlock(); return err; } diff --git a/trunk/net/mac80211/debugfs.c b/trunk/net/mac80211/debugfs.c index 82c807723b6f..96991b68f048 100644 --- a/trunk/net/mac80211/debugfs.c +++ b/trunk/net/mac80211/debugfs.c @@ -1,4 +1,3 @@ - /* * mac80211 debugfs for wireless PHYs * @@ -39,10 +38,16 @@ static const struct file_operations name## _ops = { \ }; #define DEBUGFS_ADD(name) \ - debugfs_create_file(#name, 0400, phyd, local, &name## _ops); + local->debugfs.name = debugfs_create_file(#name, 0400, phyd, \ + local, &name## _ops); #define DEBUGFS_ADD_MODE(name, mode) \ - debugfs_create_file(#name, mode, phyd, local, &name## _ops); + local->debugfs.name = debugfs_create_file(#name, mode, phyd, \ + local, &name## _ops); + +#define DEBUGFS_DEL(name) \ + debugfs_remove(local->debugfs.name); \ + local->debugfs.name = NULL; DEBUGFS_READONLY_FILE(frequency, 20, "%d", @@ -228,7 +233,12 @@ static const struct file_operations stats_ ##name## _ops = { \ }; #define DEBUGFS_STATS_ADD(name) \ - debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops); + local->debugfs.stats.name = debugfs_create_file(#name, 0400, statsd,\ + local, &stats_ ##name## _ops); + +#define DEBUGFS_STATS_DEL(name) \ + debugfs_remove(local->debugfs.stats.name); \ + local->debugfs.stats.name = NULL; DEBUGFS_STATS_FILE(transmitted_fragment_count, 20, "%u", local->dot11TransmittedFragmentCount); @@ -316,6 +326,7 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(noack); statsd = debugfs_create_dir("statistics", phyd); + local->debugfs.statistics = statsd; /* if the dir failed, don't put all the other things into the root! */ if (!statsd) @@ -356,3 +367,57 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_STATS_ADD(dot11FCSErrorCount); DEBUGFS_STATS_ADD(dot11RTSSuccessCount); } + +void debugfs_hw_del(struct ieee80211_local *local) +{ + DEBUGFS_DEL(frequency); + DEBUGFS_DEL(total_ps_buffered); + DEBUGFS_DEL(wep_iv); + DEBUGFS_DEL(tsf); + DEBUGFS_DEL(queues); + DEBUGFS_DEL(reset); + DEBUGFS_DEL(noack); + + DEBUGFS_STATS_DEL(transmitted_fragment_count); + DEBUGFS_STATS_DEL(multicast_transmitted_frame_count); + DEBUGFS_STATS_DEL(failed_count); + DEBUGFS_STATS_DEL(retry_count); + DEBUGFS_STATS_DEL(multiple_retry_count); + DEBUGFS_STATS_DEL(frame_duplicate_count); + DEBUGFS_STATS_DEL(received_fragment_count); + DEBUGFS_STATS_DEL(multicast_received_frame_count); + DEBUGFS_STATS_DEL(transmitted_frame_count); + DEBUGFS_STATS_DEL(num_scans); +#ifdef CONFIG_MAC80211_DEBUG_COUNTERS + DEBUGFS_STATS_DEL(tx_handlers_drop); + DEBUGFS_STATS_DEL(tx_handlers_queued); + DEBUGFS_STATS_DEL(tx_handlers_drop_unencrypted); + DEBUGFS_STATS_DEL(tx_handlers_drop_fragment); + DEBUGFS_STATS_DEL(tx_handlers_drop_wep); + DEBUGFS_STATS_DEL(tx_handlers_drop_not_assoc); + DEBUGFS_STATS_DEL(tx_handlers_drop_unauth_port); + DEBUGFS_STATS_DEL(rx_handlers_drop); + DEBUGFS_STATS_DEL(rx_handlers_queued); + DEBUGFS_STATS_DEL(rx_handlers_drop_nullfunc); + DEBUGFS_STATS_DEL(rx_handlers_drop_defrag); + DEBUGFS_STATS_DEL(rx_handlers_drop_short); + DEBUGFS_STATS_DEL(rx_handlers_drop_passive_scan); + DEBUGFS_STATS_DEL(tx_expand_skb_head); + DEBUGFS_STATS_DEL(tx_expand_skb_head_cloned); + DEBUGFS_STATS_DEL(rx_expand_skb_head); + DEBUGFS_STATS_DEL(rx_expand_skb_head2); + DEBUGFS_STATS_DEL(rx_handlers_fragments); + DEBUGFS_STATS_DEL(tx_status_drop); +#endif + DEBUGFS_STATS_DEL(dot11ACKFailureCount); + DEBUGFS_STATS_DEL(dot11RTSFailureCount); + DEBUGFS_STATS_DEL(dot11FCSErrorCount); + DEBUGFS_STATS_DEL(dot11RTSSuccessCount); + + debugfs_remove(local->debugfs.statistics); + local->debugfs.statistics = NULL; + debugfs_remove(local->debugfs.stations); + local->debugfs.stations = NULL; + debugfs_remove(local->debugfs.keys); + local->debugfs.keys = NULL; +} diff --git a/trunk/net/mac80211/debugfs.h b/trunk/net/mac80211/debugfs.h index 68e6a2050f9a..dd2541935c27 100644 --- a/trunk/net/mac80211/debugfs.h +++ b/trunk/net/mac80211/debugfs.h @@ -3,12 +3,14 @@ #ifdef CONFIG_MAC80211_DEBUGFS extern void debugfs_hw_add(struct ieee80211_local *local); +extern void debugfs_hw_del(struct ieee80211_local *local); extern int mac80211_open_file_generic(struct inode *inode, struct file *file); #else static inline void debugfs_hw_add(struct ieee80211_local *local) { return; } +static inline void debugfs_hw_del(struct ieee80211_local *local) {} #endif #endif /* __MAC80211_DEBUGFS_H */ diff --git a/trunk/net/mac80211/debugfs_key.c b/trunk/net/mac80211/debugfs_key.c index e0f5224630da..99c752588b30 100644 --- a/trunk/net/mac80211/debugfs_key.c +++ b/trunk/net/mac80211/debugfs_key.c @@ -225,8 +225,8 @@ static ssize_t key_key_read(struct file *file, char __user *userbuf, KEY_OPS(key); #define DEBUGFS_ADD(name) \ - debugfs_create_file(#name, 0400, key->debugfs.dir, \ - key, &key_##name##_ops); + key->debugfs.name = debugfs_create_file(#name, 0400,\ + key->debugfs.dir, key, &key_##name##_ops); void ieee80211_debugfs_key_add(struct ieee80211_key *key) { @@ -271,12 +271,30 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) DEBUGFS_ADD(ifindex); }; +#define DEBUGFS_DEL(name) \ + debugfs_remove(key->debugfs.name); key->debugfs.name = NULL; + void ieee80211_debugfs_key_remove(struct ieee80211_key *key) { if (!key) return; - debugfs_remove_recursive(key->debugfs.dir); + DEBUGFS_DEL(keylen); + DEBUGFS_DEL(flags); + DEBUGFS_DEL(keyidx); + DEBUGFS_DEL(hw_key_idx); + DEBUGFS_DEL(tx_rx_count); + DEBUGFS_DEL(algorithm); + DEBUGFS_DEL(tx_spec); + DEBUGFS_DEL(rx_spec); + DEBUGFS_DEL(replays); + DEBUGFS_DEL(icverrors); + DEBUGFS_DEL(key); + DEBUGFS_DEL(ifindex); + + debugfs_remove(key->debugfs.stalink); + key->debugfs.stalink = NULL; + debugfs_remove(key->debugfs.dir); key->debugfs.dir = NULL; } void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) @@ -284,7 +302,7 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) char buf[50]; struct ieee80211_key *key; - if (!sdata->debugfs.dir) + if (!sdata->debugfsdir) return; /* this is running under the key lock */ @@ -292,9 +310,9 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) key = sdata->default_key; if (key) { sprintf(buf, "../keys/%d", key->debugfs.cnt); - sdata->debugfs.default_key = + sdata->common_debugfs.default_key = debugfs_create_symlink("default_key", - sdata->debugfs.dir, buf); + sdata->debugfsdir, buf); } else ieee80211_debugfs_key_remove_default(sdata); } @@ -304,8 +322,8 @@ void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata) if (!sdata) return; - debugfs_remove(sdata->debugfs.default_key); - sdata->debugfs.default_key = NULL; + debugfs_remove(sdata->common_debugfs.default_key); + sdata->common_debugfs.default_key = NULL; } void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) @@ -313,7 +331,7 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) char buf[50]; struct ieee80211_key *key; - if (!sdata->debugfs.dir) + if (!sdata->debugfsdir) return; /* this is running under the key lock */ @@ -321,9 +339,9 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) key = sdata->default_mgmt_key; if (key) { sprintf(buf, "../keys/%d", key->debugfs.cnt); - sdata->debugfs.default_mgmt_key = + sdata->common_debugfs.default_mgmt_key = debugfs_create_symlink("default_mgmt_key", - sdata->debugfs.dir, buf); + sdata->debugfsdir, buf); } else ieee80211_debugfs_key_remove_mgmt_default(sdata); } @@ -333,8 +351,8 @@ void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sda if (!sdata) return; - debugfs_remove(sdata->debugfs.default_mgmt_key); - sdata->debugfs.default_mgmt_key = NULL; + debugfs_remove(sdata->common_debugfs.default_mgmt_key); + sdata->common_debugfs.default_mgmt_key = NULL; } void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, diff --git a/trunk/net/mac80211/debugfs_netdev.c b/trunk/net/mac80211/debugfs_netdev.c index 8782264f49e7..61234e79022b 100644 --- a/trunk/net/mac80211/debugfs_netdev.c +++ b/trunk/net/mac80211/debugfs_netdev.c @@ -152,9 +152,9 @@ IEEE80211_IF_FILE(min_discovery_timeout, #endif -#define DEBUGFS_ADD(name, type) \ - debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ - sdata, &name##_ops); +#define DEBUGFS_ADD(name, type)\ + sdata->debugfs.type.name = debugfs_create_file(#name, 0400,\ + sdata->debugfsdir, sdata, &name##_ops); static void add_sta_files(struct ieee80211_sub_if_data *sdata) { @@ -199,32 +199,30 @@ static void add_monitor_files(struct ieee80211_sub_if_data *sdata) } #ifdef CONFIG_MAC80211_MESH +#define MESHSTATS_ADD(name)\ + sdata->mesh_stats.name = debugfs_create_file(#name, 0400,\ + sdata->mesh_stats_dir, sdata, &name##_ops); static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) { - struct dentry *dir = debugfs_create_dir("mesh_stats", - sdata->debugfs.dir); - -#define MESHSTATS_ADD(name)\ - debugfs_create_file(#name, 0400, dir, sdata, &name##_ops); - + sdata->mesh_stats_dir = debugfs_create_dir("mesh_stats", + sdata->debugfsdir); MESHSTATS_ADD(fwded_mcast); MESHSTATS_ADD(fwded_unicast); MESHSTATS_ADD(fwded_frames); MESHSTATS_ADD(dropped_frames_ttl); MESHSTATS_ADD(dropped_frames_no_route); MESHSTATS_ADD(estab_plinks); -#undef MESHSTATS_ADD } +#define MESHPARAMS_ADD(name)\ + sdata->mesh_config.name = debugfs_create_file(#name, 0600,\ + sdata->mesh_config_dir, sdata, &name##_ops); + static void add_mesh_config(struct ieee80211_sub_if_data *sdata) { - struct dentry *dir = debugfs_create_dir("mesh_config", - sdata->debugfs.dir); - -#define MESHPARAMS_ADD(name) \ - debugfs_create_file(#name, 0600, dir, sdata, &name##_ops); - + sdata->mesh_config_dir = debugfs_create_dir("mesh_config", + sdata->debugfsdir); MESHPARAMS_ADD(dot11MeshMaxRetries); MESHPARAMS_ADD(dot11MeshRetryTimeout); MESHPARAMS_ADD(dot11MeshConfirmTimeout); @@ -238,14 +236,12 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries); MESHPARAMS_ADD(path_refresh_time); MESHPARAMS_ADD(min_discovery_timeout); - -#undef MESHPARAMS_ADD } #endif static void add_files(struct ieee80211_sub_if_data *sdata) { - if (!sdata->debugfs.dir) + if (!sdata->debugfsdir) return; switch (sdata->vif.type) { @@ -278,6 +274,134 @@ static void add_files(struct ieee80211_sub_if_data *sdata) } } +#define DEBUGFS_DEL(name, type) \ + do { \ + debugfs_remove(sdata->debugfs.type.name); \ + sdata->debugfs.type.name = NULL; \ + } while (0) + +static void del_sta_files(struct ieee80211_sub_if_data *sdata) +{ + DEBUGFS_DEL(drop_unencrypted, sta); + DEBUGFS_DEL(force_unicast_rateidx, sta); + DEBUGFS_DEL(max_ratectrl_rateidx, sta); + + DEBUGFS_DEL(bssid, sta); + DEBUGFS_DEL(aid, sta); + DEBUGFS_DEL(capab, sta); +} + +static void del_ap_files(struct ieee80211_sub_if_data *sdata) +{ + DEBUGFS_DEL(drop_unencrypted, ap); + DEBUGFS_DEL(force_unicast_rateidx, ap); + DEBUGFS_DEL(max_ratectrl_rateidx, ap); + + DEBUGFS_DEL(num_sta_ps, ap); + DEBUGFS_DEL(dtim_count, ap); + DEBUGFS_DEL(num_buffered_multicast, ap); +} + +static void del_wds_files(struct ieee80211_sub_if_data *sdata) +{ + DEBUGFS_DEL(drop_unencrypted, wds); + DEBUGFS_DEL(force_unicast_rateidx, wds); + DEBUGFS_DEL(max_ratectrl_rateidx, wds); + + DEBUGFS_DEL(peer, wds); +} + +static void del_vlan_files(struct ieee80211_sub_if_data *sdata) +{ + DEBUGFS_DEL(drop_unencrypted, vlan); + DEBUGFS_DEL(force_unicast_rateidx, vlan); + DEBUGFS_DEL(max_ratectrl_rateidx, vlan); +} + +static void del_monitor_files(struct ieee80211_sub_if_data *sdata) +{ +} + +#ifdef CONFIG_MAC80211_MESH +#define MESHSTATS_DEL(name) \ + do { \ + debugfs_remove(sdata->mesh_stats.name); \ + sdata->mesh_stats.name = NULL; \ + } while (0) + +static void del_mesh_stats(struct ieee80211_sub_if_data *sdata) +{ + MESHSTATS_DEL(fwded_mcast); + MESHSTATS_DEL(fwded_unicast); + MESHSTATS_DEL(fwded_frames); + MESHSTATS_DEL(dropped_frames_ttl); + MESHSTATS_DEL(dropped_frames_no_route); + MESHSTATS_DEL(estab_plinks); + debugfs_remove(sdata->mesh_stats_dir); + sdata->mesh_stats_dir = NULL; +} + +#define MESHPARAMS_DEL(name) \ + do { \ + debugfs_remove(sdata->mesh_config.name); \ + sdata->mesh_config.name = NULL; \ + } while (0) + +static void del_mesh_config(struct ieee80211_sub_if_data *sdata) +{ + MESHPARAMS_DEL(dot11MeshMaxRetries); + MESHPARAMS_DEL(dot11MeshRetryTimeout); + MESHPARAMS_DEL(dot11MeshConfirmTimeout); + MESHPARAMS_DEL(dot11MeshHoldingTimeout); + MESHPARAMS_DEL(dot11MeshTTL); + MESHPARAMS_DEL(auto_open_plinks); + MESHPARAMS_DEL(dot11MeshMaxPeerLinks); + MESHPARAMS_DEL(dot11MeshHWMPactivePathTimeout); + MESHPARAMS_DEL(dot11MeshHWMPpreqMinInterval); + MESHPARAMS_DEL(dot11MeshHWMPnetDiameterTraversalTime); + MESHPARAMS_DEL(dot11MeshHWMPmaxPREQretries); + MESHPARAMS_DEL(path_refresh_time); + MESHPARAMS_DEL(min_discovery_timeout); + debugfs_remove(sdata->mesh_config_dir); + sdata->mesh_config_dir = NULL; +} +#endif + +static void del_files(struct ieee80211_sub_if_data *sdata) +{ + if (!sdata->debugfsdir) + return; + + switch (sdata->vif.type) { + case NL80211_IFTYPE_MESH_POINT: +#ifdef CONFIG_MAC80211_MESH + del_mesh_stats(sdata); + del_mesh_config(sdata); +#endif + break; + case NL80211_IFTYPE_STATION: + del_sta_files(sdata); + break; + case NL80211_IFTYPE_ADHOC: + /* XXX */ + break; + case NL80211_IFTYPE_AP: + del_ap_files(sdata); + break; + case NL80211_IFTYPE_WDS: + del_wds_files(sdata); + break; + case NL80211_IFTYPE_MONITOR: + del_monitor_files(sdata); + break; + case NL80211_IFTYPE_AP_VLAN: + del_vlan_files(sdata); + break; + default: + break; + } +} + static int notif_registered; void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) @@ -288,18 +412,16 @@ void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) return; sprintf(buf, "netdev:%s", sdata->dev->name); - sdata->debugfs.dir = debugfs_create_dir(buf, + sdata->debugfsdir = debugfs_create_dir(buf, sdata->local->hw.wiphy->debugfsdir); add_files(sdata); } void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) { - if (!sdata->debugfs.dir) - return; - - debugfs_remove_recursive(sdata->debugfs.dir); - sdata->debugfs.dir = NULL; + del_files(sdata); + debugfs_remove(sdata->debugfsdir); + sdata->debugfsdir = NULL; } static int netdev_notify(struct notifier_block *nb, @@ -322,7 +444,7 @@ static int netdev_notify(struct notifier_block *nb, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - dir = sdata->debugfs.dir; + dir = sdata->debugfsdir; if (!dir) return 0; diff --git a/trunk/net/mac80211/debugfs_sta.c b/trunk/net/mac80211/debugfs_sta.c index f043c29070d7..33a2e892115b 100644 --- a/trunk/net/mac80211/debugfs_sta.c +++ b/trunk/net/mac80211/debugfs_sta.c @@ -57,6 +57,7 @@ STA_FILE(tx_filtered, tx_filtered_count, LU); STA_FILE(tx_retry_failed, tx_retry_failed, LU); STA_FILE(tx_retry_count, tx_retry_count, LU); STA_FILE(last_signal, last_signal, D); +STA_FILE(last_qual, last_qual, D); STA_FILE(last_noise, last_noise, D); STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU); @@ -66,11 +67,10 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, char buf[100]; struct sta_info *sta = file->private_data; u32 staflags = get_sta_flags(sta); - int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s", + int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s", staflags & WLAN_STA_AUTH ? "AUTH\n" : "", staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "", - staflags & WLAN_STA_PS_STA ? "PS (sta)\n" : "", - staflags & WLAN_STA_PS_DRIVER ? "PS (driver)\n" : "", + staflags & WLAN_STA_PS ? "PS\n" : "", staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "", staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "", staflags & WLAN_STA_WME ? "WME\n" : "", @@ -158,9 +158,13 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, STA_OPS(agg_status); #define DEBUGFS_ADD(name) \ - debugfs_create_file(#name, 0400, \ + sta->debugfs.name = debugfs_create_file(#name, 0400, \ sta->debugfs.dir, sta, &sta_ ##name## _ops); +#define DEBUGFS_DEL(name) \ + debugfs_remove(sta->debugfs.name);\ + sta->debugfs.name = NULL; + void ieee80211_sta_debugfs_add(struct sta_info *sta) { @@ -205,12 +209,36 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) DEBUGFS_ADD(tx_retry_failed); DEBUGFS_ADD(tx_retry_count); DEBUGFS_ADD(last_signal); + DEBUGFS_ADD(last_qual); DEBUGFS_ADD(last_noise); DEBUGFS_ADD(wep_weak_iv_count); } void ieee80211_sta_debugfs_remove(struct sta_info *sta) { - debugfs_remove_recursive(sta->debugfs.dir); + DEBUGFS_DEL(flags); + DEBUGFS_DEL(num_ps_buf_frames); + DEBUGFS_DEL(inactive_ms); + DEBUGFS_DEL(last_seq_ctrl); + DEBUGFS_DEL(agg_status); + DEBUGFS_DEL(aid); + DEBUGFS_DEL(dev); + DEBUGFS_DEL(rx_packets); + DEBUGFS_DEL(tx_packets); + DEBUGFS_DEL(rx_bytes); + DEBUGFS_DEL(tx_bytes); + DEBUGFS_DEL(rx_duplicates); + DEBUGFS_DEL(rx_fragments); + DEBUGFS_DEL(rx_dropped); + DEBUGFS_DEL(tx_fragments); + DEBUGFS_DEL(tx_filtered); + DEBUGFS_DEL(tx_retry_failed); + DEBUGFS_DEL(tx_retry_count); + DEBUGFS_DEL(last_signal); + DEBUGFS_DEL(last_qual); + DEBUGFS_DEL(last_noise); + DEBUGFS_DEL(wep_weak_iv_count); + + debugfs_remove(sta->debugfs.dir); sta->debugfs.dir = NULL; } diff --git a/trunk/net/mac80211/ht.c b/trunk/net/mac80211/ht.c index 48ef1a282b91..0891bfb06996 100644 --- a/trunk/net/mac80211/ht.c +++ b/trunk/net/mac80211/ht.c @@ -153,7 +153,7 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, if (net_ratelimit()) printk(KERN_DEBUG "delba from %pM (%s) tid %d reason code %d\n", mgmt->sa, initiator ? "initiator" : "recipient", tid, - le16_to_cpu(mgmt->u.action.u.delba.reason_code)); + mgmt->u.action.u.delba.reason_code); #endif /* CONFIG_MAC80211_HT_DEBUG */ if (initiator == WLAN_BACK_INITIATOR) diff --git a/trunk/net/mac80211/ibss.c b/trunk/net/mac80211/ibss.c index fbffce90edbc..ca8ecce31d34 100644 --- a/trunk/net/mac80211/ibss.c +++ b/trunk/net/mac80211/ibss.c @@ -73,7 +73,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt; u8 *pos; struct ieee80211_supported_band *sband; - struct cfg80211_bss *bss; u32 bss_change; u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; @@ -178,9 +177,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, mod_timer(&ifibss->timer, round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); - bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel, - mgmt, skb->len, 0, GFP_KERNEL); - cfg80211_put_bss(bss); + cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel, + mgmt, skb->len, 0, GFP_KERNEL); cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); } @@ -455,10 +453,6 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT); - if (time_before(jiffies, ifibss->last_scan_completed + - IEEE80211_IBSS_MERGE_INTERVAL)) - return; - if (ieee80211_sta_active_ibss(sdata)) return; diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index 1ef767366b77..588005c84a6d 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -176,6 +176,7 @@ struct ieee80211_rx_data { struct ieee80211_rate *rate; unsigned int flags; + int sent_ps_buffered; int queue; u32 tkip_iv32; u16 tkip_iv16; @@ -470,11 +471,74 @@ struct ieee80211_sub_if_data { } u; #ifdef CONFIG_MAC80211_DEBUGFS + struct dentry *debugfsdir; + union { + struct { + struct dentry *drop_unencrypted; + struct dentry *bssid; + struct dentry *aid; + struct dentry *capab; + struct dentry *force_unicast_rateidx; + struct dentry *max_ratectrl_rateidx; + } sta; + struct { + struct dentry *drop_unencrypted; + struct dentry *num_sta_ps; + struct dentry *dtim_count; + struct dentry *force_unicast_rateidx; + struct dentry *max_ratectrl_rateidx; + struct dentry *num_buffered_multicast; + } ap; + struct { + struct dentry *drop_unencrypted; + struct dentry *peer; + struct dentry *force_unicast_rateidx; + struct dentry *max_ratectrl_rateidx; + } wds; + struct { + struct dentry *drop_unencrypted; + struct dentry *force_unicast_rateidx; + struct dentry *max_ratectrl_rateidx; + } vlan; + struct { + struct dentry *mode; + } monitor; + } debugfs; struct { - struct dentry *dir; struct dentry *default_key; struct dentry *default_mgmt_key; - } debugfs; + } common_debugfs; + +#ifdef CONFIG_MAC80211_MESH + struct dentry *mesh_stats_dir; + struct { + struct dentry *fwded_mcast; + struct dentry *fwded_unicast; + struct dentry *fwded_frames; + struct dentry *dropped_frames_ttl; + struct dentry *dropped_frames_no_route; + struct dentry *estab_plinks; + struct timer_list mesh_path_timer; + } mesh_stats; + + struct dentry *mesh_config_dir; + struct { + struct dentry *dot11MeshRetryTimeout; + struct dentry *dot11MeshConfirmTimeout; + struct dentry *dot11MeshHoldingTimeout; + struct dentry *dot11MeshMaxRetries; + struct dentry *dot11MeshTTL; + struct dentry *auto_open_plinks; + struct dentry *dot11MeshMaxPeerLinks; + struct dentry *dot11MeshHWMPactivePathTimeout; + struct dentry *dot11MeshHWMPpreqMinInterval; + struct dentry *dot11MeshHWMPnetDiameterTraversalTime; + struct dentry *dot11MeshHWMPmaxPREQretries; + struct dentry *path_refresh_time; + struct dentry *min_discovery_timeout; + } mesh_config; +#endif + #endif /* must be last, dynamically sized area in this! */ struct ieee80211_vif vif; @@ -666,9 +730,10 @@ struct ieee80211_local { unsigned long scanning; struct cfg80211_ssid scan_ssid; struct cfg80211_scan_request *int_scan_req; - struct cfg80211_scan_request *scan_req, *hw_scan_req; + struct cfg80211_scan_request *scan_req; struct ieee80211_channel *scan_channel; - enum ieee80211_band hw_scan_band; + const u8 *orig_ies; + int orig_ies_len; int scan_channel_idx; int scan_ies_len; @@ -753,6 +818,53 @@ struct ieee80211_local { #ifdef CONFIG_MAC80211_DEBUGFS struct local_debugfsdentries { struct dentry *rcdir; + struct dentry *rcname; + struct dentry *frequency; + struct dentry *total_ps_buffered; + struct dentry *wep_iv; + struct dentry *tsf; + struct dentry *queues; + struct dentry *reset; + struct dentry *noack; + struct dentry *statistics; + struct local_debugfsdentries_statsdentries { + struct dentry *transmitted_fragment_count; + struct dentry *multicast_transmitted_frame_count; + struct dentry *failed_count; + struct dentry *retry_count; + struct dentry *multiple_retry_count; + struct dentry *frame_duplicate_count; + struct dentry *received_fragment_count; + struct dentry *multicast_received_frame_count; + struct dentry *transmitted_frame_count; + struct dentry *wep_undecryptable_count; + struct dentry *num_scans; +#ifdef CONFIG_MAC80211_DEBUG_COUNTERS + struct dentry *tx_handlers_drop; + struct dentry *tx_handlers_queued; + struct dentry *tx_handlers_drop_unencrypted; + struct dentry *tx_handlers_drop_fragment; + struct dentry *tx_handlers_drop_wep; + struct dentry *tx_handlers_drop_not_assoc; + struct dentry *tx_handlers_drop_unauth_port; + struct dentry *rx_handlers_drop; + struct dentry *rx_handlers_queued; + struct dentry *rx_handlers_drop_nullfunc; + struct dentry *rx_handlers_drop_defrag; + struct dentry *rx_handlers_drop_short; + struct dentry *rx_handlers_drop_passive_scan; + struct dentry *tx_expand_skb_head; + struct dentry *tx_expand_skb_head_cloned; + struct dentry *rx_expand_skb_head; + struct dentry *rx_expand_skb_head2; + struct dentry *rx_handlers_fragments; + struct dentry *tx_status_drop; +#endif + struct dentry *dot11ACKFailureCount; + struct dentry *dot11RTSFailureCount; + struct dentry *dot11FCSErrorCount; + struct dentry *dot11RTSSuccessCount; + } stats; struct dentry *stations; struct dentry *keys; } debugfs; @@ -1048,8 +1160,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, u8 *extra, size_t extra_len, const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx); int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, - const u8 *ie, size_t ie_len, - enum ieee80211_band band); + const u8 *ie, size_t ie_len); void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len); diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c index 8495161b99b8..14f10eb91c5c 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -214,8 +214,8 @@ static int ieee80211_open(struct net_device *dev) /* must be before the call to ieee80211_configure_filter */ local->monitors++; if (local->monitors == 1) { - local->hw.conf.flags |= IEEE80211_CONF_MONITOR; - hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; + local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; + hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP; } if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) @@ -435,8 +435,8 @@ static int ieee80211_stop(struct net_device *dev) local->monitors--; if (local->monitors == 0) { - local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; - hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; + local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; + hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP; } if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) diff --git a/trunk/net/mac80211/key.h b/trunk/net/mac80211/key.h index a49f93b79e92..9572e00f532c 100644 --- a/trunk/net/mac80211/key.h +++ b/trunk/net/mac80211/key.h @@ -118,6 +118,18 @@ struct ieee80211_key { struct { struct dentry *stalink; struct dentry *dir; + struct dentry *keylen; + struct dentry *flags; + struct dentry *keyidx; + struct dentry *hw_key_idx; + struct dentry *tx_rx_count; + struct dentry *algorithm; + struct dentry *tx_spec; + struct dentry *rx_spec; + struct dentry *replays; + struct dentry *icverrors; + struct dentry *key; + struct dentry *ifindex; int cnt; } debugfs; #endif diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index beb8718d905e..797f53942e5f 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -385,13 +385,13 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, * can be unknown, for example with different interrupt status * bits. */ - if (test_sta_flags(sta, WLAN_STA_PS_STA) && + if (test_sta_flags(sta, WLAN_STA_PS) && skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { skb_queue_tail(&sta->tx_filtered, skb); return; } - if (!test_sta_flags(sta, WLAN_STA_PS_STA) && + if (!test_sta_flags(sta, WLAN_STA_PS) && !(info->flags & IEEE80211_TX_INTFL_RETRIED)) { /* Software retry the packet once */ info->flags |= IEEE80211_TX_INTFL_RETRIED; @@ -406,7 +406,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, "queue_len=%d PS=%d @%lu\n", wiphy_name(local->hw.wiphy), skb_queue_len(&sta->tx_filtered), - !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); + !!test_sta_flags(sta, WLAN_STA_PS), jiffies); #endif dev_kfree_skb(skb); } @@ -446,7 +446,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) if (sta) { if (!(info->flags & IEEE80211_TX_STAT_ACK) && - test_sta_flags(sta, WLAN_STA_PS_STA)) { + test_sta_flags(sta, WLAN_STA_PS)) { /* * The STA is in power save mode, so assume * that this TX packet failed because of that. @@ -901,7 +901,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) i++; } } - local->int_scan_req->n_channels = i; local->network_latency_notifier.notifier_call = ieee80211_max_network_latency; @@ -924,6 +923,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) fail_wep: sta_info_stop(local); fail_sta_info: + debugfs_hw_del(local); destroy_workqueue(local->workqueue); fail_workqueue: wiphy_unregister(local->hw.wiphy); @@ -959,6 +959,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) ieee80211_clear_tx_pending(local); sta_info_stop(local); rate_control_deinitialize(local); + debugfs_hw_del(local); if (skb_queue_len(&local->skb_queue) || skb_queue_len(&local->skb_queue_unreliable)) diff --git a/trunk/net/mac80211/rate.c b/trunk/net/mac80211/rate.c index ccda7454fb17..b33efc4fc267 100644 --- a/trunk/net/mac80211/rate.c +++ b/trunk/net/mac80211/rate.c @@ -163,7 +163,8 @@ struct rate_control_ref *rate_control_alloc(const char *name, #ifdef CONFIG_MAC80211_DEBUGFS debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); local->debugfs.rcdir = debugfsdir; - debugfs_create_file("name", 0400, debugfsdir, ref, &rcname_ops); + local->debugfs.rcname = debugfs_create_file("name", 0400, debugfsdir, + ref, &rcname_ops); #endif ref->priv = ref->ops->alloc(&local->hw, debugfsdir); @@ -187,7 +188,9 @@ static void rate_control_release(struct kref *kref) ctrl_ref->ops->free(ctrl_ref->priv); #ifdef CONFIG_MAC80211_DEBUGFS - debugfs_remove_recursive(ctrl_ref->local->debugfs.rcdir); + debugfs_remove(ctrl_ref->local->debugfs.rcname); + ctrl_ref->local->debugfs.rcname = NULL; + debugfs_remove(ctrl_ref->local->debugfs.rcdir); ctrl_ref->local->debugfs.rcdir = NULL; #endif diff --git a/trunk/net/mac80211/rx.c b/trunk/net/mac80211/rx.c index 28316b2a585f..5c385e3c1d1f 100644 --- a/trunk/net/mac80211/rx.c +++ b/trunk/net/mac80211/rx.c @@ -39,8 +39,11 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, * only useful for monitoring. */ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, - struct sk_buff *skb) + struct sk_buff *skb, + int rtap_len) { + skb_pull(skb, rtap_len); + if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { if (likely(skb->len > FCS_LEN)) skb_trim(skb, skb->len - FCS_LEN); @@ -56,14 +59,15 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, } static inline int should_drop_frame(struct sk_buff *skb, - int present_fcs_len) + int present_fcs_len, + int radiotap_len) { struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) return 1; - if (unlikely(skb->len < 16 + present_fcs_len)) + if (unlikely(skb->len < 16 + present_fcs_len + radiotap_len)) return 1; if (ieee80211_is_ctl(hdr->frame_control) && !ieee80211_is_pspoll(hdr->frame_control) && @@ -91,6 +95,10 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, if (len & 1) /* padding for RX_FLAGS if necessary */ len++; + /* make sure radiotap starts at a naturally aligned address */ + if (len % 8) + len = roundup(len, 8); + return len; } @@ -108,7 +116,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_radiotap_header *rthdr; unsigned char *pos; - u16 rx_flags = 0; rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); memset(rthdr, 0, rtap_len); @@ -127,7 +134,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, /* IEEE80211_RADIOTAP_TSFT */ if (status->flag & RX_FLAG_TSFT) { - put_unaligned_le64(status->mactime, pos); + *(__le64 *)pos = cpu_to_le64(status->mactime); rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); pos += 8; @@ -159,17 +166,17 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, pos++; /* IEEE80211_RADIOTAP_CHANNEL */ - put_unaligned_le16(status->freq, pos); + *(__le16 *)pos = cpu_to_le16(status->freq); pos += 2; if (status->band == IEEE80211_BAND_5GHZ) - put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, - pos); + *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | + IEEE80211_CHAN_5GHZ); else if (rate->flags & IEEE80211_RATE_ERP_G) - put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, - pos); + *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | + IEEE80211_CHAN_2GHZ); else - put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, - pos); + *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_CCK | + IEEE80211_CHAN_2GHZ); pos += 2; /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ @@ -198,11 +205,10 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, /* IEEE80211_RADIOTAP_RX_FLAGS */ /* ensure 2 byte alignment for the 2 byte field as required */ - if ((pos - (u8 *)rthdr) & 1) + if ((pos - (unsigned char *)rthdr) & 1) pos++; if (status->flag & RX_FLAG_FAILED_PLCP_CRC) - rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP; - put_unaligned_le16(rx_flags, pos); + *(__le16 *)pos |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADPLCP); pos += 2; } @@ -221,6 +227,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, struct sk_buff *skb, *skb2; struct net_device *prev_dev = NULL; int present_fcs_len = 0; + int rtap_len = 0; /* * First, we may need to make a copy of the skb because @@ -230,23 +237,25 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, * We don't need to, of course, if we aren't going to return * the SKB because it has a bad FCS/PLCP checksum. */ - - /* room for the radiotap header based on driver features */ - needed_headroom = ieee80211_rx_radiotap_len(local, status); + if (status->flag & RX_FLAG_RADIOTAP) + rtap_len = ieee80211_get_radiotap_len(origskb->data); + else + /* room for the radiotap header based on driver features */ + needed_headroom = ieee80211_rx_radiotap_len(local, status); if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) present_fcs_len = FCS_LEN; if (!local->monitors) { - if (should_drop_frame(origskb, present_fcs_len)) { + if (should_drop_frame(origskb, present_fcs_len, rtap_len)) { dev_kfree_skb(origskb); return NULL; } - return remove_monitor_info(local, origskb); + return remove_monitor_info(local, origskb, rtap_len); } - if (should_drop_frame(origskb, present_fcs_len)) { + if (should_drop_frame(origskb, present_fcs_len, rtap_len)) { /* only need to expand headroom if necessary */ skb = origskb; origskb = NULL; @@ -270,14 +279,16 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, */ skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC); - origskb = remove_monitor_info(local, origskb); + origskb = remove_monitor_info(local, origskb, rtap_len); if (!skb) return origskb; } - /* prepend radiotap information */ - ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom); + /* if necessary, prepend radiotap information */ + if (!(status->flag & RX_FLAG_RADIOTAP)) + ieee80211_add_rx_radiotap_header(local, skb, rate, + needed_headroom); skb_reset_mac_header(skb); skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -781,7 +792,7 @@ static void ap_sta_ps_start(struct sta_info *sta) struct ieee80211_local *local = sdata->local; atomic_inc(&sdata->bss->num_sta_ps); - set_sta_flags(sta, WLAN_STA_PS_STA); + set_sta_flags(sta, WLAN_STA_PS); drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta); #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", @@ -789,28 +800,38 @@ static void ap_sta_ps_start(struct sta_info *sta) #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ } -static void ap_sta_ps_end(struct sta_info *sta) +static int ap_sta_ps_end(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; + struct ieee80211_local *local = sdata->local; + int sent, buffered; atomic_dec(&sdata->bss->num_sta_ps); - clear_sta_flags(sta, WLAN_STA_PS_STA); + clear_sta_flags(sta, WLAN_STA_PS); + drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta); + + if (!skb_queue_empty(&sta->ps_tx_buf)) + sta_info_clear_tim_bit(sta); #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", sdata->dev->name, sta->sta.addr, sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ - if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) { + /* Send all buffered frames to the station */ + sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); + buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf); + sent += buffered; + local->total_ps_buffered -= buffered; + #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", - sdata->dev->name, sta->sta.addr, sta->sta.aid); + printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " + "since STA not sleeping anymore\n", sdata->dev->name, + sta->sta.addr, sta->sta.aid, sent - buffered, buffered); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ - return; - } - ieee80211_sta_ps_deliver_wakeup(sta); + return sent; } static ieee80211_rx_result debug_noinline @@ -849,6 +870,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) sta->rx_fragments++; sta->rx_bytes += rx->skb->len; sta->last_signal = rx->status->signal; + sta->last_qual = rx->status->qual; sta->last_noise = rx->status->noise; /* @@ -858,7 +880,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) if (!ieee80211_has_morefrags(hdr->frame_control) && (rx->sdata->vif.type == NL80211_IFTYPE_AP || rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { - if (test_sta_flags(sta, WLAN_STA_PS_STA)) { + if (test_sta_flags(sta, WLAN_STA_PS)) { /* * Ignore doze->wake transitions that are * indicated by non-data frames, the standard @@ -869,24 +891,19 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) */ if (ieee80211_is_data(hdr->frame_control) && !ieee80211_has_pm(hdr->frame_control)) - ap_sta_ps_end(sta); + rx->sent_ps_buffered += ap_sta_ps_end(sta); } else { if (ieee80211_has_pm(hdr->frame_control)) ap_sta_ps_start(sta); } } - /* - * Drop (qos-)data::nullfunc frames silently, since they - * are used only to control station power saving mode. - */ - if (ieee80211_is_nullfunc(hdr->frame_control) || - ieee80211_is_qos_nullfunc(hdr->frame_control)) { + /* Drop data::nullfunc frames silently, since they are used only to + * control station power saving mode. */ + if (ieee80211_is_nullfunc(hdr->frame_control)) { I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc); - /* - * Update counter and free packet here to avoid - * counting this as a dropped packed. - */ + /* Update counter and free packet here to avoid counting this + * as a dropped packed. */ sta->rx_packets++; dev_kfree_skb(rx->skb); return RX_QUEUED; @@ -1086,7 +1103,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) static ieee80211_rx_result debug_noinline ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) { - struct ieee80211_sub_if_data *sdata = rx->sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); + struct sk_buff *skb; + int no_pending_pkts; __le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control; if (likely(!rx->sta || !ieee80211_is_pspoll(fc) || @@ -1097,10 +1116,56 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) return RX_DROP_UNUSABLE; - if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER)) - ieee80211_sta_ps_deliver_poll_response(rx->sta); - else - set_sta_flags(rx->sta, WLAN_STA_PSPOLL); + skb = skb_dequeue(&rx->sta->tx_filtered); + if (!skb) { + skb = skb_dequeue(&rx->sta->ps_tx_buf); + if (skb) + rx->local->total_ps_buffered--; + } + no_pending_pkts = skb_queue_empty(&rx->sta->tx_filtered) && + skb_queue_empty(&rx->sta->ps_tx_buf); + + if (skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = + (struct ieee80211_hdr *) skb->data; + + /* + * Tell TX path to send this frame even though the STA may + * still remain is PS mode after this frame exchange. + */ + info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE; + +#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG + printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n", + rx->sta->sta.addr, rx->sta->sta.aid, + skb_queue_len(&rx->sta->ps_tx_buf)); +#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ + + /* Use MoreData flag to indicate whether there are more + * buffered frames for this STA */ + if (no_pending_pkts) + hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA); + else + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); + + ieee80211_add_pending_skb(rx->local, skb); + + if (no_pending_pkts) + sta_info_clear_tim_bit(rx->sta); +#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG + } else if (!rx->sent_ps_buffered) { + /* + * FIXME: This can be the result of a race condition between + * us expiring a frame and the station polling for it. + * Should we send it a null-func frame indicating we + * have nothing buffered for it? + */ + printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " + "though there are no buffered frames for it\n", + rx->dev->name, rx->sta->sta.addr); +#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ + } /* Free PS Poll skb here instead of returning RX_DROP that would * count as an dropped frame. */ @@ -1272,10 +1337,10 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) skb = NULL; } else { u8 *data = skb->data; - size_t len = skb_headlen(skb); - skb->data -= align; - memmove(skb->data, data, len); - skb_set_tail_pointer(skb, len); + size_t len = skb->len; + u8 *new = __skb_push(skb, align); + memmove(new, data, len); + __skb_trim(skb, len); } } #endif diff --git a/trunk/net/mac80211/scan.c b/trunk/net/mac80211/scan.c index 4cf387c944bf..7a350d2690a0 100644 --- a/trunk/net/mac80211/scan.c +++ b/trunk/net/mac80211/scan.c @@ -12,6 +12,8 @@ * published by the Free Software Foundation. */ +/* TODO: figure out how to avoid that the "current BSS" expires */ + #include #include #include @@ -187,39 +189,6 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) return RX_QUEUED; } -/* return false if no more work */ -static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) -{ - struct cfg80211_scan_request *req = local->scan_req; - enum ieee80211_band band; - int i, ielen, n_chans; - - do { - if (local->hw_scan_band == IEEE80211_NUM_BANDS) - return false; - - band = local->hw_scan_band; - n_chans = 0; - for (i = 0; i < req->n_channels; i++) { - if (req->channels[i]->band == band) { - local->hw_scan_req->channels[n_chans] = - req->channels[i]; - n_chans++; - } - } - - local->hw_scan_band++; - } while (!n_chans); - - local->hw_scan_req->n_channels = n_chans; - - ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, - req->ie, req->ie_len, band); - local->hw_scan_req->ie_len = ielen; - - return true; -} - /* * inform AP that we will go to sleep so that it will buffer the frames * while we scan @@ -280,6 +249,13 @@ static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) } } +static void ieee80211_restore_scan_ies(struct ieee80211_local *local) +{ + kfree(local->scan_req->ie); + local->scan_req->ie = local->orig_ies; + local->scan_req->ie_len = local->orig_ies_len; +} + void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) { struct ieee80211_local *local = hw_to_local(hw); @@ -288,36 +264,25 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) mutex_lock(&local->scan_mtx); - /* - * It's ok to abort a not-yet-running scan (that - * we have one at all will be verified by checking - * local->scan_req next), but not to complete it - * successfully. - */ - if (WARN_ON(!local->scanning && !aborted)) - aborted = true; - - if (WARN_ON(!local->scan_req)) { + if (WARN_ON(!local->scanning)) { mutex_unlock(&local->scan_mtx); return; } - was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning); - if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { - ieee80211_queue_delayed_work(&local->hw, - &local->scan_work, 0); + if (WARN_ON(!local->scan_req)) { mutex_unlock(&local->scan_mtx); return; } - kfree(local->hw_scan_req); - local->hw_scan_req = NULL; + if (test_bit(SCAN_HW_SCANNING, &local->scanning)) + ieee80211_restore_scan_ies(local); if (local->scan_req != local->int_scan_req) cfg80211_scan_done(local->scan_req, aborted); local->scan_req = NULL; local->scan_sdata = NULL; + was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning); local->scanning = 0; local->scan_channel = NULL; @@ -429,23 +394,19 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, if (local->ops->hw_scan) { u8 *ies; + int ielen; - local->hw_scan_req = kmalloc( - sizeof(*local->hw_scan_req) + - req->n_channels * sizeof(req->channels[0]) + - 2 + IEEE80211_MAX_SSID_LEN + local->scan_ies_len + - req->ie_len, GFP_KERNEL); - if (!local->hw_scan_req) + ies = kmalloc(2 + IEEE80211_MAX_SSID_LEN + + local->scan_ies_len + req->ie_len, GFP_KERNEL); + if (!ies) return -ENOMEM; - local->hw_scan_req->ssids = req->ssids; - local->hw_scan_req->n_ssids = req->n_ssids; - ies = (u8 *)local->hw_scan_req + - sizeof(*local->hw_scan_req) + - req->n_channels * sizeof(req->channels[0]); - local->hw_scan_req->ie = ies; - - local->hw_scan_band = 0; + ielen = ieee80211_build_preq_ies(local, ies, + req->ie, req->ie_len); + local->orig_ies = req->ie; + local->orig_ies_len = req->ie_len; + req->ie = ies; + req->ie_len = ielen; } local->scan_req = req; @@ -477,17 +438,16 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, ieee80211_recalc_idle(local); mutex_unlock(&local->scan_mtx); - if (local->ops->hw_scan) { - WARN_ON(!ieee80211_prep_hw_scan(local)); - rc = drv_hw_scan(local, local->hw_scan_req); - } else + if (local->ops->hw_scan) + rc = drv_hw_scan(local, local->scan_req); + else rc = ieee80211_start_sw_scan(local); mutex_lock(&local->scan_mtx); if (rc) { - kfree(local->hw_scan_req); - local->hw_scan_req = NULL; + if (local->ops->hw_scan) + ieee80211_restore_scan_ies(local); local->scanning = 0; ieee80211_recalc_idle(local); @@ -614,14 +574,23 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, { int skip; struct ieee80211_channel *chan; + struct ieee80211_sub_if_data *sdata = local->scan_sdata; skip = 0; chan = local->scan_req->channels[local->scan_channel_idx]; - local->scan_channel = chan; - if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) + if (chan->flags & IEEE80211_CHAN_DISABLED || + (sdata->vif.type == NL80211_IFTYPE_ADHOC && + chan->flags & IEEE80211_CHAN_NO_IBSS)) skip = 1; + if (!skip) { + local->scan_channel = chan; + if (ieee80211_hw_config(local, + IEEE80211_CONF_CHANGE_CHANNEL)) + skip = 1; + } + /* advance state machine to next channel/band */ local->scan_channel_idx++; @@ -687,14 +656,6 @@ void ieee80211_scan_work(struct work_struct *work) return; } - if (local->hw_scan_req) { - int rc = drv_hw_scan(local, local->hw_scan_req); - mutex_unlock(&local->scan_mtx); - if (rc) - ieee80211_scan_completed(&local->hw, true); - return; - } - if (local->scan_req && !local->scanning) { struct cfg80211_scan_request *req = local->scan_req; int rc; diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index be59456e8a42..594f2318c3d8 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -171,8 +171,6 @@ void sta_info_destroy(struct sta_info *sta) local = sta->local; - cancel_work_sync(&sta->drv_unblock_wk); - rate_control_remove_sta_debugfs(sta); ieee80211_sta_debugfs_remove(sta); @@ -261,21 +259,6 @@ static void sta_info_hash_add(struct ieee80211_local *local, rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); } -static void sta_unblock(struct work_struct *wk) -{ - struct sta_info *sta; - - sta = container_of(wk, struct sta_info, drv_unblock_wk); - - if (sta->dead) - return; - - if (!test_sta_flags(sta, WLAN_STA_PS_STA)) - ieee80211_sta_ps_deliver_wakeup(sta); - else if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) - ieee80211_sta_ps_deliver_poll_response(sta); -} - struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr, gfp_t gfp) { @@ -289,7 +272,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, spin_lock_init(&sta->lock); spin_lock_init(&sta->flaglock); - INIT_WORK(&sta->drv_unblock_wk, sta_unblock); memcpy(sta->sta.addr, addr, ETH_ALEN); sta->local = local; @@ -496,10 +478,8 @@ static void __sta_info_unlink(struct sta_info **sta) } list_del(&(*sta)->list); - (*sta)->dead = true; - if (test_and_clear_sta_flags(*sta, - WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { + if (test_and_clear_sta_flags(*sta, WLAN_STA_PS)) { BUG_ON(!sdata->bss); atomic_dec(&sdata->bss->num_sta_ps); @@ -821,8 +801,8 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, sta_info_destroy(sta); } -struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, - const u8 *addr) +struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, + const u8 *addr) { struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); @@ -830,114 +810,4 @@ struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, return NULL; return &sta->sta; } -EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); - -struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, - const u8 *addr) -{ - struct ieee80211_sub_if_data *sdata; - - if (!vif) - return NULL; - - sdata = vif_to_sdata(vif); - - return ieee80211_find_sta_by_hw(&sdata->local->hw, addr); -} EXPORT_SYMBOL(ieee80211_find_sta); - -/* powersave support code */ -void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct ieee80211_local *local = sdata->local; - int sent, buffered; - - drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta); - - if (!skb_queue_empty(&sta->ps_tx_buf)) - sta_info_clear_tim_bit(sta); - - /* Send all buffered frames to the station */ - sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); - buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf); - sent += buffered; - local->total_ps_buffered -= buffered; - -#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " - "since STA not sleeping anymore\n", sdata->dev->name, - sta->sta.addr, sta->sta.aid, sent - buffered, buffered); -#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ -} - -void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - int no_pending_pkts; - - skb = skb_dequeue(&sta->tx_filtered); - if (!skb) { - skb = skb_dequeue(&sta->ps_tx_buf); - if (skb) - local->total_ps_buffered--; - } - no_pending_pkts = skb_queue_empty(&sta->tx_filtered) && - skb_queue_empty(&sta->ps_tx_buf); - - if (skb) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *) skb->data; - - /* - * Tell TX path to send this frame even though the STA may - * still remain is PS mode after this frame exchange. - */ - info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE; - -#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n", - sta->sta.addr, sta->sta.aid, - skb_queue_len(&sta->ps_tx_buf)); -#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ - - /* Use MoreData flag to indicate whether there are more - * buffered frames for this STA */ - if (no_pending_pkts) - hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA); - else - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); - - ieee80211_add_pending_skb(local, skb); - - if (no_pending_pkts) - sta_info_clear_tim_bit(sta); -#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - } else { - /* - * FIXME: This can be the result of a race condition between - * us expiring a frame and the station polling for it. - * Should we send it a null-func frame indicating we - * have nothing buffered for it? - */ - printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " - "though there are no buffered frames for it\n", - sdata->dev->name, sta->sta.addr); -#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ - } -} - -void ieee80211_sta_block_awake(struct ieee80211_hw *hw, - struct ieee80211_sta *pubsta, bool block) -{ - struct sta_info *sta = container_of(pubsta, struct sta_info, sta); - - if (block) - set_sta_flags(sta, WLAN_STA_PS_DRIVER); - else - ieee80211_queue_work(hw, &sta->drv_unblock_wk); -} -EXPORT_SYMBOL(ieee80211_sta_block_awake); diff --git a/trunk/net/mac80211/sta_info.h b/trunk/net/mac80211/sta_info.h index 4673454176ed..ccc3adf962c7 100644 --- a/trunk/net/mac80211/sta_info.h +++ b/trunk/net/mac80211/sta_info.h @@ -12,7 +12,6 @@ #include #include #include -#include #include "key.h" /** @@ -22,7 +21,7 @@ * * @WLAN_STA_AUTH: Station is authenticated. * @WLAN_STA_ASSOC: Station is associated. - * @WLAN_STA_PS_STA: Station is in power-save mode + * @WLAN_STA_PS: Station is in power-save mode * @WLAN_STA_AUTHORIZED: Station is authorized to send/receive traffic. * This bit is always checked so needs to be enabled for all stations * when virtual port control is not in use. @@ -37,16 +36,11 @@ * @WLAN_STA_MFP: Management frame protection is used with this STA. * @WLAN_STA_SUSPEND: Set/cleared during a suspend/resume cycle. * Used to deny ADDBA requests (both TX and RX). - * @WLAN_STA_PS_DRIVER: driver requires keeping this station in - * power-save mode logically to flush frames that might still - * be in the queues - * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping - * station in power-save mode, reply when the driver unblocks. */ enum ieee80211_sta_info_flags { WLAN_STA_AUTH = 1<<0, WLAN_STA_ASSOC = 1<<1, - WLAN_STA_PS_STA = 1<<2, + WLAN_STA_PS = 1<<2, WLAN_STA_AUTHORIZED = 1<<3, WLAN_STA_SHORT_PREAMBLE = 1<<4, WLAN_STA_ASSOC_AP = 1<<5, @@ -54,9 +48,7 @@ enum ieee80211_sta_info_flags { WLAN_STA_WDS = 1<<7, WLAN_STA_CLEAR_PS_FILT = 1<<9, WLAN_STA_MFP = 1<<10, - WLAN_STA_SUSPEND = 1<<11, - WLAN_STA_PS_DRIVER = 1<<12, - WLAN_STA_PSPOLL = 1<<13, + WLAN_STA_SUSPEND = 1<<11 }; #define STA_TID_NUM 16 @@ -201,6 +193,7 @@ struct sta_ampdu_mlme { * @rx_fragments: number of received MPDUs * @rx_dropped: number of dropped MPDUs from this STA * @last_signal: signal of last received frame from this STA + * @last_qual: qual of last received frame from this STA * @last_noise: noise of last received frame from this STA * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) * @tx_filtered_count: number of frames the hardware filtered for this STA @@ -224,8 +217,6 @@ struct sta_ampdu_mlme { * @plink_timer_was_running: used by suspend/resume to restore timers * @debugfs: debug filesystem info * @sta: station information we share with the driver - * @dead: set to true when sta is unlinked - * @drv_unblock_wk used for driver PS unblocking */ struct sta_info { /* General information, mostly static */ @@ -239,12 +230,8 @@ struct sta_info { spinlock_t lock; spinlock_t flaglock; - struct work_struct drv_unblock_wk; - u16 listen_interval; - bool dead; - /* * for use by the internal lifetime management, * see __sta_info_unlink @@ -272,6 +259,7 @@ struct sta_info { unsigned long rx_fragments; unsigned long rx_dropped; int last_signal; + int last_qual; int last_noise; __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; @@ -313,6 +301,28 @@ struct sta_info { #ifdef CONFIG_MAC80211_DEBUGFS struct sta_info_debugfsdentries { struct dentry *dir; + struct dentry *flags; + struct dentry *num_ps_buf_frames; + struct dentry *inactive_ms; + struct dentry *last_seq_ctrl; + struct dentry *agg_status; + struct dentry *aid; + struct dentry *dev; + struct dentry *rx_packets; + struct dentry *tx_packets; + struct dentry *rx_bytes; + struct dentry *tx_bytes; + struct dentry *rx_duplicates; + struct dentry *rx_fragments; + struct dentry *rx_dropped; + struct dentry *tx_fragments; + struct dentry *tx_filtered; + struct dentry *tx_retry_failed; + struct dentry *tx_retry_count; + struct dentry *last_signal; + struct dentry *last_qual; + struct dentry *last_noise; + struct dentry *wep_weak_iv_count; bool add_has_run; } debugfs; #endif @@ -444,7 +454,4 @@ int sta_info_flush(struct ieee80211_local *local, void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, unsigned long exp_time); -void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); -void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); - #endif /* STA_INFO_H */ diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index bfaa43e096d2..eaa4118de988 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -317,11 +317,12 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) if (!atomic_read(&tx->sdata->bss->num_sta_ps)) return TX_CONTINUE; - info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; + /* buffered in hardware */ + if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) { + info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; - /* device releases frame after DTIM beacon */ - if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) return TX_CONTINUE; + } /* buffered in mac80211 */ if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) @@ -374,7 +375,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) staflags = get_sta_flags(sta); - if (unlikely((staflags & (WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) && + if (unlikely((staflags & WLAN_STA_PS) && !(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE))) { #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "STA %pM aid %d: PS buffer (entries " @@ -397,13 +398,8 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) } else tx->local->total_ps_buffered++; - /* - * Queue frame to be sent after STA wakes up/polls, - * but don't set the TIM bit if the driver is blocking - * wakeup or poll response transmissions anyway. - */ - if (skb_queue_empty(&sta->ps_tx_buf) && - !(staflags & WLAN_STA_PS_DRIVER)) + /* Queue frame to be sent after STA sends an PS Poll frame */ + if (skb_queue_empty(&sta->ps_tx_buf)) sta_info_set_tim_bit(sta); info->control.jiffies = jiffies; @@ -413,7 +409,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) return TX_QUEUED; } #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - else if (unlikely(staflags & WLAN_STA_PS_STA)) { + else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) { printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll " "set -> send frame\n", tx->dev->name, sta->sta.addr); @@ -1205,25 +1201,23 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) struct sk_buff *skb = tx->skb; ieee80211_tx_result res = TX_DROP; -#define CALL_TXH(txh) \ - do { \ - res = txh(tx); \ - if (res != TX_CONTINUE) \ - goto txh_done; \ - } while (0) - - CALL_TXH(ieee80211_tx_h_check_assoc); - CALL_TXH(ieee80211_tx_h_ps_buf); - CALL_TXH(ieee80211_tx_h_select_key); - CALL_TXH(ieee80211_tx_h_michael_mic_add); - CALL_TXH(ieee80211_tx_h_rate_ctrl); - CALL_TXH(ieee80211_tx_h_misc); - CALL_TXH(ieee80211_tx_h_sequence); - CALL_TXH(ieee80211_tx_h_fragment); +#define CALL_TXH(txh) \ + res = txh(tx); \ + if (res != TX_CONTINUE) \ + goto txh_done; + + CALL_TXH(ieee80211_tx_h_check_assoc) + CALL_TXH(ieee80211_tx_h_ps_buf) + CALL_TXH(ieee80211_tx_h_select_key) + CALL_TXH(ieee80211_tx_h_michael_mic_add) + CALL_TXH(ieee80211_tx_h_rate_ctrl) + CALL_TXH(ieee80211_tx_h_misc) + CALL_TXH(ieee80211_tx_h_sequence) + CALL_TXH(ieee80211_tx_h_fragment) /* handlers after fragment must be aware of tx info fragmentation! */ - CALL_TXH(ieee80211_tx_h_stats); - CALL_TXH(ieee80211_tx_h_encrypt); - CALL_TXH(ieee80211_tx_h_calculate_duration); + CALL_TXH(ieee80211_tx_h_stats) + CALL_TXH(ieee80211_tx_h_encrypt) + CALL_TXH(ieee80211_tx_h_calculate_duration) #undef CALL_TXH txh_done: @@ -1393,30 +1387,6 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, return 0; } -static bool need_dynamic_ps(struct ieee80211_local *local) -{ - /* driver doesn't support power save */ - if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) - return false; - - /* hardware does dynamic power save */ - if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) - return false; - - /* dynamic power save disabled */ - if (local->hw.conf.dynamic_ps_timeout <= 0) - return false; - - /* we are scanning, don't enable power save */ - if (local->scanning) - return false; - - if (!local->ps_sdata) - return false; - - return true; -} - static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { @@ -1429,7 +1399,9 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, dev_hold(sdata->dev); - if (need_dynamic_ps(local)) { + if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && + local->hw.conf.dynamic_ps_timeout > 0 && + !(local->scanning) && local->ps_sdata) { if (local->hw.conf.flags & IEEE80211_CONF_PS) { ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_QUEUE_STOP_REASON_PS); @@ -2018,9 +1990,8 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss, } } -struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - u16 *tim_offset, u16 *tim_length) +struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct ieee80211_local *local = hw_to_local(hw); struct sk_buff *skb = NULL; @@ -2037,11 +2008,6 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, sdata = vif_to_sdata(vif); - if (tim_offset) - *tim_offset = 0; - if (tim_length) - *tim_length = 0; - if (sdata->vif.type == NL80211_IFTYPE_AP) { ap = &sdata->u.ap; beacon = rcu_dereference(ap->beacon); @@ -2077,11 +2043,6 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, spin_unlock_irqrestore(&local->sta_lock, flags); } - if (tim_offset) - *tim_offset = beacon->head_len; - if (tim_length) - *tim_length = skb->len - beacon->head_len; - if (beacon->tail) memcpy(skb_put(skb, beacon->tail_len), beacon->tail, beacon->tail_len); @@ -2158,7 +2119,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, rcu_read_unlock(); return skb; } -EXPORT_SYMBOL(ieee80211_beacon_get_tim); +EXPORT_SYMBOL(ieee80211_beacon_get); void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const void *frame, size_t frame_len, diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index aedbaaa067e6..aeb65b3d2295 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -872,14 +872,13 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, } int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, - const u8 *ie, size_t ie_len, - enum ieee80211_band band) + const u8 *ie, size_t ie_len) { struct ieee80211_supported_band *sband; u8 *pos, *supp_rates_len, *esupp_rates_len = NULL; int i; - sband = local->hw.wiphy->bands[band]; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; pos = buffer; @@ -967,8 +966,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, memcpy(pos, ssid, ssid_len); pos += ssid_len; - skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len, - local->hw.conf.channel->band)); + skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len)); ieee80211_tx_skb(sdata, skb, 0); } diff --git a/trunk/net/netfilter/nf_conntrack_core.c b/trunk/net/netfilter/nf_conntrack_core.c index 0cdfb388a191..7c9ec3dee96e 100644 --- a/trunk/net/netfilter/nf_conntrack_core.c +++ b/trunk/net/netfilter/nf_conntrack_core.c @@ -1350,11 +1350,6 @@ static int nf_conntrack_init_net(struct net *net) return ret; } -s16 (*nf_ct_nat_offset)(const struct nf_conn *ct, - enum ip_conntrack_dir dir, - u32 seq); -EXPORT_SYMBOL_GPL(nf_ct_nat_offset); - int nf_conntrack_init(struct net *net) { int ret; @@ -1372,9 +1367,6 @@ int nf_conntrack_init(struct net *net) /* For use by REJECT target */ rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach); rcu_assign_pointer(nf_ct_destroy, destroy_conntrack); - - /* Howto get NAT offsets */ - rcu_assign_pointer(nf_ct_nat_offset, NULL); } return 0; diff --git a/trunk/net/netfilter/nf_conntrack_proto_tcp.c b/trunk/net/netfilter/nf_conntrack_proto_tcp.c index ba2b76937283..97a82ba75376 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_tcp.c +++ b/trunk/net/netfilter/nf_conntrack_proto_tcp.c @@ -492,21 +492,6 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff, } } -#ifdef CONFIG_NF_NAT_NEEDED -static inline s16 nat_offset(const struct nf_conn *ct, - enum ip_conntrack_dir dir, - u32 seq) -{ - typeof(nf_ct_nat_offset) get_offset = rcu_dereference(nf_ct_nat_offset); - - return get_offset != NULL ? get_offset(ct, dir, seq) : 0; -} -#define NAT_OFFSET(pf, ct, dir, seq) \ - (pf == NFPROTO_IPV4 ? nat_offset(ct, dir, seq) : 0) -#else -#define NAT_OFFSET(pf, ct, dir, seq) 0 -#endif - static bool tcp_in_window(const struct nf_conn *ct, struct ip_ct_tcp *state, enum ip_conntrack_dir dir, @@ -521,7 +506,6 @@ static bool tcp_in_window(const struct nf_conn *ct, struct ip_ct_tcp_state *receiver = &state->seen[!dir]; const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; __u32 seq, ack, sack, end, win, swin; - s16 receiver_offset; bool res; /* @@ -535,16 +519,11 @@ static bool tcp_in_window(const struct nf_conn *ct, if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM) tcp_sack(skb, dataoff, tcph, &sack); - /* Take into account NAT sequence number mangling */ - receiver_offset = NAT_OFFSET(pf, ct, !dir, ack - 1); - ack -= receiver_offset; - sack -= receiver_offset; - pr_debug("tcp_in_window: START\n"); pr_debug("tcp_in_window: "); nf_ct_dump_tuple(tuple); - pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n", - seq, ack, receiver_offset, sack, receiver_offset, win, end); + pr_debug("seq=%u ack=%u sack=%u win=%u end=%u\n", + seq, ack, sack, win, end); pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " "receiver end=%u maxend=%u maxwin=%u scale=%i\n", sender->td_end, sender->td_maxend, sender->td_maxwin, @@ -634,8 +613,8 @@ static bool tcp_in_window(const struct nf_conn *ct, pr_debug("tcp_in_window: "); nf_ct_dump_tuple(tuple); - pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n", - seq, ack, receiver_offset, sack, receiver_offset, win, end); + pr_debug("seq=%u ack=%u sack =%u win=%u end=%u\n", + seq, ack, sack, win, end); pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " "receiver end=%u maxend=%u maxwin=%u scale=%i\n", sender->td_end, sender->td_maxend, sender->td_maxwin, @@ -721,7 +700,7 @@ static bool tcp_in_window(const struct nf_conn *ct, before(seq, sender->td_maxend + 1) ? after(end, sender->td_end - receiver->td_maxwin - 1) ? before(sack, receiver->td_end + 1) ? - after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1) ? "BUG" + after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG" : "ACK is under the lower bound (possible overly delayed ACK)" : "ACK is over the upper bound (ACKed data not seen yet)" : "SEQ is under the lower bound (already ACKed data retransmitted)" @@ -736,6 +715,39 @@ static bool tcp_in_window(const struct nf_conn *ct, return res; } +#ifdef CONFIG_NF_NAT_NEEDED +/* Update sender->td_end after NAT successfully mangled the packet */ +/* Caller must linearize skb at tcp header. */ +void nf_conntrack_tcp_update(const struct sk_buff *skb, + unsigned int dataoff, + struct nf_conn *ct, int dir, + s16 offset) +{ + const struct tcphdr *tcph = (const void *)skb->data + dataoff; + const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[dir]; + const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[!dir]; + __u32 end; + + end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph); + + spin_lock_bh(&ct->lock); + /* + * We have to worry for the ack in the reply packet only... + */ + if (ct->proto.tcp.seen[dir].td_end + offset == end) + ct->proto.tcp.seen[dir].td_end = end; + ct->proto.tcp.last_end = end; + spin_unlock_bh(&ct->lock); + pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i " + "receiver end=%u maxend=%u maxwin=%u scale=%i\n", + sender->td_end, sender->td_maxend, sender->td_maxwin, + sender->td_scale, + receiver->td_end, receiver->td_maxend, receiver->td_maxwin, + receiver->td_scale); +} +EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update); +#endif + #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 diff --git a/trunk/net/netfilter/xt_connlimit.c b/trunk/net/netfilter/xt_connlimit.c index 38f03f75a636..680980954395 100644 --- a/trunk/net/netfilter/xt_connlimit.c +++ b/trunk/net/netfilter/xt_connlimit.c @@ -103,7 +103,7 @@ static int count_them(struct xt_connlimit_data *data, const struct nf_conntrack_tuple *tuple, const union nf_inet_addr *addr, const union nf_inet_addr *mask, - u_int8_t family) + const struct xt_match *match) { const struct nf_conntrack_tuple_hash *found; struct xt_connlimit_conn *conn; @@ -113,7 +113,8 @@ static int count_them(struct xt_connlimit_data *data, bool addit = true; int matches = 0; - if (family == NFPROTO_IPV6) + + if (match->family == NFPROTO_IPV6) hash = &data->iphash[connlimit_iphash6(addr, mask)]; else hash = &data->iphash[connlimit_iphash(addr->ip & mask->ip)]; @@ -156,7 +157,8 @@ static int count_them(struct xt_connlimit_data *data, continue; } - if (same_source_net(addr, mask, &conn->tuple.src.u3, family)) + if (same_source_net(addr, mask, &conn->tuple.src.u3, + match->family)) /* same source network -> be counted! */ ++matches; nf_ct_put(found_ct); @@ -205,7 +207,7 @@ connlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par) spin_lock_bh(&info->data->lock); connections = count_them(info->data, tuple_ptr, &addr, - &info->mask, par->family); + &info->mask, par->match); spin_unlock_bh(&info->data->lock); if (connections < 0) { diff --git a/trunk/net/netlabel/netlabel_unlabeled.c b/trunk/net/netlabel/netlabel_unlabeled.c index 3dfe2bac8623..fb357f010189 100644 --- a/trunk/net/netlabel/netlabel_unlabeled.c +++ b/trunk/net/netlabel/netlabel_unlabeled.c @@ -472,12 +472,13 @@ int netlbl_unlhsh_add(struct net *net, rcu_read_lock(); if (dev_name != NULL) { - dev = dev_get_by_name_rcu(net, dev_name); + dev = dev_get_by_name(net, dev_name); if (dev == NULL) { ret_val = -ENODEV; goto unlhsh_add_return; } ifindex = dev->ifindex; + dev_put(dev); iface = netlbl_unlhsh_search_iface(ifindex); } else { ifindex = 0; @@ -736,12 +737,13 @@ int netlbl_unlhsh_remove(struct net *net, rcu_read_lock(); if (dev_name != NULL) { - dev = dev_get_by_name_rcu(net, dev_name); + dev = dev_get_by_name(net, dev_name); if (dev == NULL) { ret_val = -ENODEV; goto unlhsh_remove_return; } iface = netlbl_unlhsh_search_iface(dev->ifindex); + dev_put(dev); } else iface = rcu_dereference(netlbl_unlhsh_def); if (iface == NULL) { diff --git a/trunk/net/netlink/af_netlink.c b/trunk/net/netlink/af_netlink.c index f30d596dbc58..0cd2d8829313 100644 --- a/trunk/net/netlink/af_netlink.c +++ b/trunk/net/netlink/af_netlink.c @@ -428,8 +428,7 @@ static int __netlink_create(struct net *net, struct socket *sock, return 0; } -static int netlink_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int netlink_create(struct net *net, struct socket *sock, int protocol) { struct module *module = NULL; struct mutex *cb_mutex; @@ -708,7 +707,7 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr, { struct sock *sk = sock->sk; struct netlink_sock *nlk = nlk_sk(sk); - DECLARE_SOCKADDR(struct sockaddr_nl *, nladdr, addr); + struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; nladdr->nl_family = AF_NETLINK; nladdr->nl_pad = 0; diff --git a/trunk/net/netrom/af_netrom.c b/trunk/net/netrom/af_netrom.c index 4bdd5697f63b..281fa597cae5 100644 --- a/trunk/net/netrom/af_netrom.c +++ b/trunk/net/netrom/af_netrom.c @@ -425,8 +425,7 @@ static struct proto nr_proto = { .obj_size = sizeof(struct nr_sock), }; -static int nr_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int nr_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; struct nr_sock *nr; diff --git a/trunk/net/packet/af_packet.c b/trunk/net/packet/af_packet.c index c620bd9ae3de..91d246d34780 100644 --- a/trunk/net/packet/af_packet.c +++ b/trunk/net/packet/af_packet.c @@ -1344,8 +1344,7 @@ static struct proto packet_proto = { * Create a packet of type SOCK_PACKET. */ -static int packet_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int packet_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; struct packet_sock *po; @@ -1537,7 +1536,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr, struct net_device *dev; struct sock *sk = sock->sk; struct packet_sock *po = pkt_sk(sk); - DECLARE_SOCKADDR(struct sockaddr_ll *, sll, uaddr); + struct sockaddr_ll *sll = (struct sockaddr_ll *)uaddr; if (peer) return -EOPNOTSUPP; diff --git a/trunk/net/phonet/af_phonet.c b/trunk/net/phonet/af_phonet.c index ed65da251b6a..66737aa995ea 100644 --- a/trunk/net/phonet/af_phonet.c +++ b/trunk/net/phonet/af_phonet.c @@ -35,6 +35,7 @@ /* Transport protocol registration */ static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly; +static DEFINE_SPINLOCK(proto_tab_lock); static struct phonet_protocol *phonet_proto_get(int protocol) { @@ -43,11 +44,11 @@ static struct phonet_protocol *phonet_proto_get(int protocol) if (protocol >= PHONET_NPROTO) return NULL; - rcu_read_lock(); + spin_lock(&proto_tab_lock); pp = proto_tab[protocol]; if (pp && !try_module_get(pp->prot->owner)) pp = NULL; - rcu_read_unlock(); + spin_unlock(&proto_tab_lock); return pp; } @@ -59,8 +60,7 @@ static inline void phonet_proto_put(struct phonet_protocol *pp) /* protocol family functions */ -static int pn_socket_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int pn_socket_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; struct pn_sock *pn; @@ -438,8 +438,6 @@ static struct packet_type phonet_packet_type __read_mostly = { .func = phonet_rcv, }; -static DEFINE_MUTEX(proto_tab_lock); - int __init_or_module phonet_proto_register(int protocol, struct phonet_protocol *pp) { @@ -452,12 +450,12 @@ int __init_or_module phonet_proto_register(int protocol, if (err) return err; - mutex_lock(&proto_tab_lock); + spin_lock(&proto_tab_lock); if (proto_tab[protocol]) err = -EBUSY; else - rcu_assign_pointer(proto_tab[protocol], pp); - mutex_unlock(&proto_tab_lock); + proto_tab[protocol] = pp; + spin_unlock(&proto_tab_lock); return err; } @@ -465,11 +463,10 @@ EXPORT_SYMBOL(phonet_proto_register); void phonet_proto_unregister(int protocol, struct phonet_protocol *pp) { - mutex_lock(&proto_tab_lock); + spin_lock(&proto_tab_lock); BUG_ON(proto_tab[protocol] != pp); - rcu_assign_pointer(proto_tab[protocol], NULL); - mutex_unlock(&proto_tab_lock); - synchronize_rcu(); + proto_tab[protocol] = NULL; + spin_unlock(&proto_tab_lock); proto_unregister(pp->prot); } EXPORT_SYMBOL(phonet_proto_unregister); @@ -483,7 +480,6 @@ static int __init phonet_init(void) if (err) return err; - pn_sock_init(); err = sock_register(&phonet_proto_family); if (err) { printk(KERN_ALERT diff --git a/trunk/net/phonet/pep.c b/trunk/net/phonet/pep.c index bdc17bdad366..cbaa1d67d77b 100644 --- a/trunk/net/phonet/pep.c +++ b/trunk/net/phonet/pep.c @@ -843,7 +843,7 @@ static int pep_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len) { struct pep_sock *pn = pep_sk(sk); - struct sk_buff *skb; + struct sk_buff *skb = NULL; long timeo; int flags = msg->msg_flags; int err, done; @@ -851,16 +851,6 @@ static int pep_sendmsg(struct kiocb *iocb, struct sock *sk, if (msg->msg_flags & MSG_OOB || !(msg->msg_flags & MSG_EOR)) return -EOPNOTSUPP; - skb = sock_alloc_send_skb(sk, MAX_PNPIPE_HEADER + len, - flags & MSG_DONTWAIT, &err); - if (!skb) - return -ENOBUFS; - - skb_reserve(skb, MAX_PHONET_HEADER + 3); - err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); - if (err < 0) - goto outfree; - lock_sock(sk); timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); if ((1 << sk->sk_state) & (TCPF_LISTEN|TCPF_CLOSE)) { @@ -904,13 +894,28 @@ static int pep_sendmsg(struct kiocb *iocb, struct sock *sk, goto disabled; } + if (!skb) { + skb = sock_alloc_send_skb(sk, MAX_PNPIPE_HEADER + len, + flags & MSG_DONTWAIT, &err); + if (skb == NULL) + goto out; + skb_reserve(skb, MAX_PHONET_HEADER + 3); + + if (sk->sk_state != TCP_ESTABLISHED || + !atomic_read(&pn->tx_credits)) + goto disabled; /* sock_alloc_send_skb might sleep */ + } + + err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); + if (err < 0) + goto out; + err = pipe_skb_send(sk, skb); if (err >= 0) err = len; /* success! */ skb = NULL; out: release_sock(sk); -outfree: kfree_skb(skb); return err; } diff --git a/trunk/net/phonet/pn_dev.c b/trunk/net/phonet/pn_dev.c index 3287f8f0b5cc..6d64fda1afc9 100644 --- a/trunk/net/phonet/pn_dev.c +++ b/trunk/net/phonet/pn_dev.c @@ -34,7 +34,7 @@ #include struct phonet_routes { - struct mutex lock; + spinlock_t lock; struct net_device *table[64]; }; @@ -248,22 +248,17 @@ static void phonet_route_autodel(struct net_device *dev) /* Remove left-over Phonet routes */ bitmap_zero(deleted, 64); - mutex_lock(&pnn->routes.lock); + spin_lock_bh(&pnn->routes.lock); for (i = 0; i < 64; i++) if (dev == pnn->routes.table[i]) { - rcu_assign_pointer(pnn->routes.table[i], NULL); set_bit(i, deleted); + pnn->routes.table[i] = NULL; + dev_put(dev); } - mutex_unlock(&pnn->routes.lock); - - if (bitmap_empty(deleted, 64)) - return; /* short-circuit RCU */ - synchronize_rcu(); + spin_unlock_bh(&pnn->routes.lock); for (i = find_first_bit(deleted, 64); i < 64; - i = find_next_bit(deleted, 64, i + 1)) { + i = find_next_bit(deleted, 64, i + 1)) rtm_phonet_notify(RTM_DELROUTE, dev, i); - dev_put(dev); - } } /* notify Phonet of device events */ @@ -305,7 +300,7 @@ static int phonet_init_net(struct net *net) INIT_LIST_HEAD(&pnn->pndevs.list); spin_lock_init(&pnn->pndevs.lock); - mutex_init(&pnn->routes.lock); + spin_lock_init(&pnn->routes.lock); net_assign_generic(net, phonet_net_id, pnn); return 0; } @@ -366,13 +361,13 @@ int phonet_route_add(struct net_device *dev, u8 daddr) int err = -EEXIST; daddr = daddr >> 2; - mutex_lock(&routes->lock); + spin_lock_bh(&routes->lock); if (routes->table[daddr] == NULL) { - rcu_assign_pointer(routes->table[daddr], dev); + routes->table[daddr] = dev; dev_hold(dev); err = 0; } - mutex_unlock(&routes->lock); + spin_unlock_bh(&routes->lock); return err; } @@ -380,20 +375,17 @@ int phonet_route_del(struct net_device *dev, u8 daddr) { struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id); struct phonet_routes *routes = &pnn->routes; + int err = -ENOENT; daddr = daddr >> 2; - mutex_lock(&routes->lock); - if (dev == routes->table[daddr]) - rcu_assign_pointer(routes->table[daddr], NULL); - else - dev = NULL; - mutex_unlock(&routes->lock); - - if (!dev) - return -ENOENT; - synchronize_rcu(); - dev_put(dev); - return 0; + spin_lock_bh(&routes->lock); + if (dev == routes->table[daddr]) { + routes->table[daddr] = NULL; + dev_put(dev); + err = 0; + } + spin_unlock_bh(&routes->lock); + return err; } struct net_device *phonet_route_get(struct net *net, u8 daddr) @@ -405,9 +397,9 @@ struct net_device *phonet_route_get(struct net *net, u8 daddr) ASSERT_RTNL(); /* no need to hold the device */ daddr >>= 2; - rcu_read_lock(); - dev = rcu_dereference(routes->table[daddr]); - rcu_read_unlock(); + spin_lock_bh(&routes->lock); + dev = routes->table[daddr]; + spin_unlock_bh(&routes->lock); return dev; } @@ -417,12 +409,11 @@ struct net_device *phonet_route_output(struct net *net, u8 daddr) struct phonet_routes *routes = &pnn->routes; struct net_device *dev; - daddr >>= 2; - rcu_read_lock(); - dev = rcu_dereference(routes->table[daddr]); + spin_lock_bh(&routes->lock); + dev = routes->table[daddr >> 2]; if (dev) dev_hold(dev); - rcu_read_unlock(); + spin_unlock_bh(&routes->lock); if (!dev) dev = phonet_device_get(net); /* Default route */ diff --git a/trunk/net/phonet/socket.c b/trunk/net/phonet/socket.c index 4112b6e1c48a..0412beb59a05 100644 --- a/trunk/net/phonet/socket.c +++ b/trunk/net/phonet/socket.c @@ -45,28 +45,13 @@ static int pn_socket_release(struct socket *sock) return 0; } -#define PN_HASHSIZE 16 -#define PN_HASHMASK (PN_HASHSIZE-1) - - static struct { - struct hlist_head hlist[PN_HASHSIZE]; + struct hlist_head hlist; spinlock_t lock; -} pnsocks; - -void __init pn_sock_init(void) -{ - unsigned i; - - for (i = 0; i < PN_HASHSIZE; i++) - INIT_HLIST_HEAD(pnsocks.hlist + i); - spin_lock_init(&pnsocks.lock); -} - -static struct hlist_head *pn_hash_list(u16 obj) -{ - return pnsocks.hlist + (obj & PN_HASHMASK); -} +} pnsocks = { + .hlist = HLIST_HEAD_INIT, + .lock = __SPIN_LOCK_UNLOCKED(pnsocks.lock), +}; /* * Find address based on socket address, match only certain fields. @@ -79,11 +64,10 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn) struct sock *rval = NULL; u16 obj = pn_sockaddr_get_object(spn); u8 res = spn->spn_resource; - struct hlist_head *hlist = pn_hash_list(obj); spin_lock_bh(&pnsocks.lock); - sk_for_each(sknode, node, hlist) { + sk_for_each(sknode, node, &pnsocks.hlist) { struct pn_sock *pn = pn_sk(sknode); BUG_ON(!pn->sobject); /* unbound socket */ @@ -115,39 +99,31 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn) /* Deliver a broadcast packet (only in bottom-half) */ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb) { - struct hlist_head *hlist = pnsocks.hlist; - unsigned h; + struct hlist_node *node; + struct sock *sknode; spin_lock(&pnsocks.lock); - for (h = 0; h < PN_HASHSIZE; h++) { - struct hlist_node *node; - struct sock *sknode; - - sk_for_each(sknode, node, hlist) { - struct sk_buff *clone; + sk_for_each(sknode, node, &pnsocks.hlist) { + struct sk_buff *clone; - if (!net_eq(sock_net(sknode), net)) - continue; - if (!sock_flag(sknode, SOCK_BROADCAST)) - continue; + if (!net_eq(sock_net(sknode), net)) + continue; + if (!sock_flag(sknode, SOCK_BROADCAST)) + continue; - clone = skb_clone(skb, GFP_ATOMIC); - if (clone) { - sock_hold(sknode); - sk_receive_skb(sknode, clone, 0); - } + clone = skb_clone(skb, GFP_ATOMIC); + if (clone) { + sock_hold(sknode); + sk_receive_skb(sknode, clone, 0); } - hlist++; } spin_unlock(&pnsocks.lock); } void pn_sock_hash(struct sock *sk) { - struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject); - spin_lock_bh(&pnsocks.lock); - sk_add_node(sk, hlist); + sk_add_node(sk, &pnsocks.hlist); spin_unlock_bh(&pnsocks.lock); } EXPORT_SYMBOL(pn_sock_hash); @@ -463,20 +439,15 @@ EXPORT_SYMBOL(pn_sock_get_port); static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos) { struct net *net = seq_file_net(seq); - struct hlist_head *hlist = pnsocks.hlist; struct hlist_node *node; struct sock *sknode; - unsigned h; - for (h = 0; h < PN_HASHSIZE; h++) { - sk_for_each(sknode, node, hlist) { - if (!net_eq(net, sock_net(sknode))) - continue; - if (!pos) - return sknode; - pos--; - } - hlist++; + sk_for_each(sknode, node, &pnsocks.hlist) { + if (!net_eq(net, sock_net(sknode))) + continue; + if (!pos) + return sknode; + pos--; } return NULL; } diff --git a/trunk/net/rds/af_rds.c b/trunk/net/rds/af_rds.c index e25d8d5ce8df..2b978dc6e75d 100644 --- a/trunk/net/rds/af_rds.c +++ b/trunk/net/rds/af_rds.c @@ -410,8 +410,7 @@ static int __rds_create(struct socket *sock, struct sock *sk, int protocol) return 0; } -static int rds_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int rds_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; diff --git a/trunk/net/rose/af_rose.c b/trunk/net/rose/af_rose.c index 4de4287fec37..c17734c2ce89 100644 --- a/trunk/net/rose/af_rose.c +++ b/trunk/net/rose/af_rose.c @@ -512,8 +512,7 @@ static struct proto rose_proto = { .obj_size = sizeof(struct rose_sock), }; -static int rose_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int rose_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; struct rose_sock *rose; diff --git a/trunk/net/rose/rose_route.c b/trunk/net/rose/rose_route.c index ea2e72337e2f..d936226916f2 100644 --- a/trunk/net/rose/rose_route.c +++ b/trunk/net/rose/rose_route.c @@ -578,18 +578,18 @@ static int rose_clear_routes(void) /* * Check that the device given is a valid AX.25 interface that is "up". - * called whith RTNL */ -static struct net_device *rose_ax25_dev_find(char *devname) +static struct net_device *rose_ax25_dev_get(char *devname) { struct net_device *dev; - if ((dev = __dev_get_by_name(&init_net, devname)) == NULL) + if ((dev = dev_get_by_name(&init_net, devname)) == NULL) return NULL; if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25) return dev; + dev_put(dev); return NULL; } @@ -720,23 +720,27 @@ int rose_rt_ioctl(unsigned int cmd, void __user *arg) case SIOCADDRT: if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct))) return -EFAULT; - if ((dev = rose_ax25_dev_find(rose_route.device)) == NULL) + if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL) return -EINVAL; - if (rose_dev_exists(&rose_route.address)) /* Can't add routes to ourself */ + if (rose_dev_exists(&rose_route.address)) { /* Can't add routes to ourself */ + dev_put(dev); return -EINVAL; + } if (rose_route.mask > 10) /* Mask can't be more than 10 digits */ return -EINVAL; if (rose_route.ndigis > AX25_MAX_DIGIS) return -EINVAL; err = rose_add_node(&rose_route, dev); + dev_put(dev); return err; case SIOCDELRT: if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct))) return -EFAULT; - if ((dev = rose_ax25_dev_find(rose_route.device)) == NULL) + if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL) return -EINVAL; err = rose_del_node(&rose_route, dev); + dev_put(dev); return err; case SIOCRSCLRRT: diff --git a/trunk/net/rxrpc/af_rxrpc.c b/trunk/net/rxrpc/af_rxrpc.c index f978d02a248a..6817c9781ef3 100644 --- a/trunk/net/rxrpc/af_rxrpc.c +++ b/trunk/net/rxrpc/af_rxrpc.c @@ -608,8 +608,7 @@ static unsigned int rxrpc_poll(struct file *file, struct socket *sock, /* * create an RxRPC socket */ -static int rxrpc_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int rxrpc_create(struct net *net, struct socket *sock, int protocol) { struct rxrpc_sock *rx; struct sock *sk; diff --git a/trunk/net/sched/cls_api.c b/trunk/net/sched/cls_api.c index c024da77824f..7cf6c0fbc7a6 100644 --- a/trunk/net/sched/cls_api.c +++ b/trunk/net/sched/cls_api.c @@ -404,7 +404,6 @@ static int tcf_node_dump(struct tcf_proto *tp, unsigned long n, a->cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWTFILTER); } -/* called with RTNL */ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) { struct net *net = sock_net(skb->sk); @@ -423,7 +422,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) return skb->len; - if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) + if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) return skb->len; if (!tcm->tcm_parent) @@ -485,6 +484,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) if (cl) cops->put(q, cl); out: + dev_put(dev); return skb->len; } diff --git a/trunk/net/sched/sch_api.c b/trunk/net/sched/sch_api.c index 876ba4bb6ae9..1acfd29cc826 100644 --- a/trunk/net/sched/sch_api.c +++ b/trunk/net/sched/sch_api.c @@ -1279,10 +1279,9 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) s_idx = cb->args[0]; s_q_idx = q_idx = cb->args[1]; - - rcu_read_lock(); + read_lock(&dev_base_lock); idx = 0; - for_each_netdev_rcu(&init_net, dev) { + for_each_netdev(&init_net, dev) { struct netdev_queue *dev_queue; if (idx < s_idx) @@ -1303,7 +1302,7 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) } done: - rcu_read_unlock(); + read_unlock(&dev_base_lock); cb->args[0] = idx; cb->args[1] = q_idx; diff --git a/trunk/net/sched/sch_generic.c b/trunk/net/sched/sch_generic.c index b13821ad2fb6..4ae6aa562f2b 100644 --- a/trunk/net/sched/sch_generic.c +++ b/trunk/net/sched/sch_generic.c @@ -120,15 +120,8 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, HARD_TX_LOCK(dev, txq, smp_processor_id()); if (!netif_tx_queue_stopped(txq) && - !netif_tx_queue_frozen(txq)) { + !netif_tx_queue_frozen(txq)) ret = dev_hard_start_xmit(skb, dev, txq); - - /* an error implies that the skb was consumed */ - if (ret < 0) - ret = NETDEV_TX_OK; - /* all NET_XMIT codes map to NETDEV_TX_OK */ - ret &= ~NET_XMIT_MASK; - } HARD_TX_UNLOCK(dev, txq); spin_lock(root_lock); diff --git a/trunk/net/sctp/ipv6.c b/trunk/net/sctp/ipv6.c index cc50fbe99291..bb280e60e00a 100644 --- a/trunk/net/sctp/ipv6.c +++ b/trunk/net/sctp/ipv6.c @@ -837,16 +837,15 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) if (type & IPV6_ADDR_LINKLOCAL) { if (!addr->v6.sin6_scope_id) return 0; - rcu_read_lock(); - dev = dev_get_by_index_rcu(&init_net, - addr->v6.sin6_scope_id); - if (!dev || - !ipv6_chk_addr(&init_net, &addr->v6.sin6_addr, + dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id); + if (!dev) + return 0; + if (!ipv6_chk_addr(&init_net, &addr->v6.sin6_addr, dev, 0)) { - rcu_read_unlock(); + dev_put(dev); return 0; } - rcu_read_unlock(); + dev_put(dev); } else if (type == IPV6_ADDR_MAPPED) { if (!opt->v4mapped) return 0; @@ -874,12 +873,10 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr) if (type & IPV6_ADDR_LINKLOCAL) { if (!addr->v6.sin6_scope_id) return 0; - rcu_read_lock(); - dev = dev_get_by_index_rcu(&init_net, - addr->v6.sin6_scope_id); - rcu_read_unlock(); + dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id); if (!dev) return 0; + dev_put(dev); } af = opt->pf->af; } @@ -933,6 +930,7 @@ static struct inet_protosw sctpv6_seqpacket_protosw = { .protocol = IPPROTO_SCTP, .prot = &sctpv6_prot, .ops = &inet6_seqpacket_ops, + .capability = -1, .no_check = 0, .flags = SCTP_PROTOSW_FLAG }; @@ -941,6 +939,7 @@ static struct inet_protosw sctpv6_stream_protosw = { .protocol = IPPROTO_SCTP, .prot = &sctpv6_prot, .ops = &inet6_seqpacket_ops, + .capability = -1, .no_check = 0, .flags = SCTP_PROTOSW_FLAG, }; diff --git a/trunk/net/sctp/protocol.c b/trunk/net/sctp/protocol.c index 08ef203d36ac..fe44c57101de 100644 --- a/trunk/net/sctp/protocol.c +++ b/trunk/net/sctp/protocol.c @@ -909,6 +909,7 @@ static struct inet_protosw sctp_seqpacket_protosw = { .protocol = IPPROTO_SCTP, .prot = &sctp_prot, .ops = &inet_seqpacket_ops, + .capability = -1, .no_check = 0, .flags = SCTP_PROTOSW_FLAG }; @@ -917,6 +918,7 @@ static struct inet_protosw sctp_stream_protosw = { .protocol = IPPROTO_SCTP, .prot = &sctp_prot, .ops = &inet_seqpacket_ops, + .capability = -1, .no_check = 0, .flags = SCTP_PROTOSW_FLAG }; diff --git a/trunk/net/socket.c b/trunk/net/socket.c index 402abb39cbfe..9dff31c9b799 100644 --- a/trunk/net/socket.c +++ b/trunk/net/socket.c @@ -97,12 +97,6 @@ #include #include -#include -#include -#include -#include -#include - static int sock_no_open(struct inode *irrelevant, struct file *dontcare); static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos); @@ -925,24 +919,6 @@ void dlci_ioctl_set(int (*hook) (unsigned int, void __user *)) EXPORT_SYMBOL(dlci_ioctl_set); -static long sock_do_ioctl(struct net *net, struct socket *sock, - unsigned int cmd, unsigned long arg) -{ - int err; - void __user *argp = (void __user *)arg; - - err = sock->ops->ioctl(sock, cmd, arg); - - /* - * If this ioctl is unknown try to hand it down - * to the NIC driver. - */ - if (err == -ENOIOCTLCMD) - err = dev_ioctl(net, cmd, argp); - - return err; -} - /* * With an ioctl, arg may well be a user mode pointer, but we don't know * what to do with it - that's up to the protocol still. @@ -1016,7 +992,14 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) mutex_unlock(&dlci_ioctl_mutex); break; default: - err = sock_do_ioctl(net, sock, cmd, arg); + err = sock->ops->ioctl(sock, cmd, arg); + + /* + * If this ioctl is unknown try to hand it down + * to the NIC driver. + */ + if (err == -ENOIOCTLCMD) + err = dev_ioctl(net, cmd, argp); break; } return err; @@ -1269,7 +1252,7 @@ static int __sock_create(struct net *net, int family, int type, int protocol, /* Now protected by module ref count */ rcu_read_unlock(); - err = pf->create(net, sock, protocol, kern); + err = pf->create(net, sock, protocol); if (err < 0) goto out_module_put; @@ -2476,552 +2459,6 @@ void socket_seq_show(struct seq_file *seq) #endif /* CONFIG_PROC_FS */ #ifdef CONFIG_COMPAT -static int do_siocgstamp(struct net *net, struct socket *sock, - unsigned int cmd, struct compat_timeval __user *up) -{ - mm_segment_t old_fs = get_fs(); - struct timeval ktv; - int err; - - set_fs(KERNEL_DS); - err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); - set_fs(old_fs); - if (!err) { - err = put_user(ktv.tv_sec, &up->tv_sec); - err |= __put_user(ktv.tv_usec, &up->tv_usec); - } - return err; -} - -static int do_siocgstampns(struct net *net, struct socket *sock, - unsigned int cmd, struct compat_timespec __user *up) -{ - mm_segment_t old_fs = get_fs(); - struct timespec kts; - int err; - - set_fs(KERNEL_DS); - err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); - set_fs(old_fs); - if (!err) { - err = put_user(kts.tv_sec, &up->tv_sec); - err |= __put_user(kts.tv_nsec, &up->tv_nsec); - } - return err; -} - -static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32) -{ - struct ifreq __user *uifr; - int err; - - uifr = compat_alloc_user_space(sizeof(struct ifreq)); - if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) - return -EFAULT; - - err = dev_ioctl(net, SIOCGIFNAME, uifr); - if (err) - return err; - - if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq))) - return -EFAULT; - - return 0; -} - -static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) -{ - struct compat_ifconf ifc32; - struct ifconf ifc; - struct ifconf __user *uifc; - struct compat_ifreq __user *ifr32; - struct ifreq __user *ifr; - unsigned int i, j; - int err; - - if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) - return -EFAULT; - - if (ifc32.ifcbuf == 0) { - ifc32.ifc_len = 0; - ifc.ifc_len = 0; - ifc.ifc_req = NULL; - uifc = compat_alloc_user_space(sizeof(struct ifconf)); - } else { - size_t len =((ifc32.ifc_len / sizeof (struct compat_ifreq)) + 1) * - sizeof (struct ifreq); - uifc = compat_alloc_user_space(sizeof(struct ifconf) + len); - ifc.ifc_len = len; - ifr = ifc.ifc_req = (void __user *)(uifc + 1); - ifr32 = compat_ptr(ifc32.ifcbuf); - for (i = 0; i < ifc32.ifc_len; i += sizeof (struct compat_ifreq)) { - if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq))) - return -EFAULT; - ifr++; - ifr32++; - } - } - if (copy_to_user(uifc, &ifc, sizeof(struct ifconf))) - return -EFAULT; - - err = dev_ioctl(net, SIOCGIFCONF, uifc); - if (err) - return err; - - if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) - return -EFAULT; - - ifr = ifc.ifc_req; - ifr32 = compat_ptr(ifc32.ifcbuf); - for (i = 0, j = 0; - i + sizeof (struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len; - i += sizeof (struct compat_ifreq), j += sizeof (struct ifreq)) { - if (copy_in_user(ifr32, ifr, sizeof (struct compat_ifreq))) - return -EFAULT; - ifr32++; - ifr++; - } - - if (ifc32.ifcbuf == 0) { - /* Translate from 64-bit structure multiple to - * a 32-bit one. - */ - i = ifc.ifc_len; - i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq)); - ifc32.ifc_len = i; - } else { - ifc32.ifc_len = i; - } - if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf))) - return -EFAULT; - - return 0; -} - -static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) -{ - struct ifreq __user *ifr; - u32 data; - void __user *datap; - - ifr = compat_alloc_user_space(sizeof(*ifr)); - - if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) - return -EFAULT; - - if (get_user(data, &ifr32->ifr_ifru.ifru_data)) - return -EFAULT; - - datap = compat_ptr(data); - if (put_user(datap, &ifr->ifr_ifru.ifru_data)) - return -EFAULT; - - return dev_ioctl(net, SIOCETHTOOL, ifr); -} - -static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) -{ - void __user *uptr; - compat_uptr_t uptr32; - struct ifreq __user *uifr; - - uifr = compat_alloc_user_space(sizeof (*uifr)); - if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) - return -EFAULT; - - if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu)) - return -EFAULT; - - uptr = compat_ptr(uptr32); - - if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc)) - return -EFAULT; - - return dev_ioctl(net, SIOCWANDEV, uifr); -} - -static int bond_ioctl(struct net *net, unsigned int cmd, - struct compat_ifreq __user *ifr32) -{ - struct ifreq kifr; - struct ifreq __user *uifr; - mm_segment_t old_fs; - int err; - u32 data; - void __user *datap; - - switch (cmd) { - case SIOCBONDENSLAVE: - case SIOCBONDRELEASE: - case SIOCBONDSETHWADDR: - case SIOCBONDCHANGEACTIVE: - if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq))) - return -EFAULT; - - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = dev_ioctl(net, cmd, &kifr); - set_fs (old_fs); - - return err; - case SIOCBONDSLAVEINFOQUERY: - case SIOCBONDINFOQUERY: - uifr = compat_alloc_user_space(sizeof(*uifr)); - if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) - return -EFAULT; - - if (get_user(data, &ifr32->ifr_ifru.ifru_data)) - return -EFAULT; - - datap = compat_ptr(data); - if (put_user(datap, &uifr->ifr_ifru.ifru_data)) - return -EFAULT; - - return dev_ioctl(net, cmd, uifr); - default: - return -EINVAL; - }; -} - -static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, - struct compat_ifreq __user *u_ifreq32) -{ - struct ifreq __user *u_ifreq64; - char tmp_buf[IFNAMSIZ]; - void __user *data64; - u32 data32; - - if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), - IFNAMSIZ)) - return -EFAULT; - if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) - return -EFAULT; - data64 = compat_ptr(data32); - - u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); - - /* Don't check these user accesses, just let that get trapped - * in the ioctl handler instead. - */ - if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], - IFNAMSIZ)) - return -EFAULT; - if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data)) - return -EFAULT; - - return dev_ioctl(net, cmd, u_ifreq64); -} - -static int dev_ifsioc(struct net *net, struct socket *sock, - unsigned int cmd, struct compat_ifreq __user *uifr32) -{ - struct ifreq __user *uifr; - int err; - - uifr = compat_alloc_user_space(sizeof(*uifr)); - if (copy_in_user(uifr, uifr32, sizeof(*uifr32))) - return -EFAULT; - - err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr); - - if (!err) { - switch (cmd) { - case SIOCGIFFLAGS: - case SIOCGIFMETRIC: - case SIOCGIFMTU: - case SIOCGIFMEM: - case SIOCGIFHWADDR: - case SIOCGIFINDEX: - case SIOCGIFADDR: - case SIOCGIFBRDADDR: - case SIOCGIFDSTADDR: - case SIOCGIFNETMASK: - case SIOCGIFPFLAGS: - case SIOCGIFTXQLEN: - case SIOCGMIIPHY: - case SIOCGMIIREG: - if (copy_in_user(uifr32, uifr, sizeof(*uifr32))) - err = -EFAULT; - break; - } - } - return err; -} - -static int compat_sioc_ifmap(struct net *net, unsigned int cmd, - struct compat_ifreq __user *uifr32) -{ - struct ifreq ifr; - struct compat_ifmap __user *uifmap32; - mm_segment_t old_fs; - int err; - - uifmap32 = &uifr32->ifr_ifru.ifru_map; - err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name)); - err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); - err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); - err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); - err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq); - err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma); - err |= __get_user(ifr.ifr_map.port, &uifmap32->port); - if (err) - return -EFAULT; - - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = dev_ioctl(net, cmd, (void __user *)&ifr); - set_fs (old_fs); - - if (cmd == SIOCGIFMAP && !err) { - err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); - err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); - err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); - err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); - err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq); - err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma); - err |= __put_user(ifr.ifr_map.port, &uifmap32->port); - if (err) - err = -EFAULT; - } - return err; -} - -static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32) -{ - void __user *uptr; - compat_uptr_t uptr32; - struct ifreq __user *uifr; - - uifr = compat_alloc_user_space(sizeof (*uifr)); - if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) - return -EFAULT; - - if (get_user(uptr32, &uifr32->ifr_data)) - return -EFAULT; - - uptr = compat_ptr(uptr32); - - if (put_user(uptr, &uifr->ifr_data)) - return -EFAULT; - - return dev_ioctl(net, SIOCSHWTSTAMP, uifr); -} - -struct rtentry32 { - u32 rt_pad1; - struct sockaddr rt_dst; /* target address */ - struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ - struct sockaddr rt_genmask; /* target network mask (IP) */ - unsigned short rt_flags; - short rt_pad2; - u32 rt_pad3; - unsigned char rt_tos; - unsigned char rt_class; - short rt_pad4; - short rt_metric; /* +1 for binary compatibility! */ - /* char * */ u32 rt_dev; /* forcing the device at add */ - u32 rt_mtu; /* per route MTU/Window */ - u32 rt_window; /* Window clamping */ - unsigned short rt_irtt; /* Initial RTT */ -}; - -struct in6_rtmsg32 { - struct in6_addr rtmsg_dst; - struct in6_addr rtmsg_src; - struct in6_addr rtmsg_gateway; - u32 rtmsg_type; - u16 rtmsg_dst_len; - u16 rtmsg_src_len; - u32 rtmsg_metric; - u32 rtmsg_info; - u32 rtmsg_flags; - s32 rtmsg_ifindex; -}; - -static int routing_ioctl(struct net *net, struct socket *sock, - unsigned int cmd, void __user *argp) -{ - int ret; - void *r = NULL; - struct in6_rtmsg r6; - struct rtentry r4; - char devname[16]; - u32 rtdev; - mm_segment_t old_fs = get_fs(); - - if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */ - struct in6_rtmsg32 __user *ur6 = argp; - ret = copy_from_user (&r6.rtmsg_dst, &(ur6->rtmsg_dst), - 3 * sizeof(struct in6_addr)); - ret |= __get_user (r6.rtmsg_type, &(ur6->rtmsg_type)); - ret |= __get_user (r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len)); - ret |= __get_user (r6.rtmsg_src_len, &(ur6->rtmsg_src_len)); - ret |= __get_user (r6.rtmsg_metric, &(ur6->rtmsg_metric)); - ret |= __get_user (r6.rtmsg_info, &(ur6->rtmsg_info)); - ret |= __get_user (r6.rtmsg_flags, &(ur6->rtmsg_flags)); - ret |= __get_user (r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); - - r = (void *) &r6; - } else { /* ipv4 */ - struct rtentry32 __user *ur4 = argp; - ret = copy_from_user (&r4.rt_dst, &(ur4->rt_dst), - 3 * sizeof(struct sockaddr)); - ret |= __get_user (r4.rt_flags, &(ur4->rt_flags)); - ret |= __get_user (r4.rt_metric, &(ur4->rt_metric)); - ret |= __get_user (r4.rt_mtu, &(ur4->rt_mtu)); - ret |= __get_user (r4.rt_window, &(ur4->rt_window)); - ret |= __get_user (r4.rt_irtt, &(ur4->rt_irtt)); - ret |= __get_user (rtdev, &(ur4->rt_dev)); - if (rtdev) { - ret |= copy_from_user (devname, compat_ptr(rtdev), 15); - r4.rt_dev = devname; devname[15] = 0; - } else - r4.rt_dev = NULL; - - r = (void *) &r4; - } - - if (ret) { - ret = -EFAULT; - goto out; - } - - set_fs (KERNEL_DS); - ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r); - set_fs (old_fs); - -out: - return ret; -} - -/* Since old style bridge ioctl's endup using SIOCDEVPRIVATE - * for some operations; this forces use of the newer bridge-utils that - * use compatiable ioctls - */ -static int old_bridge_ioctl(compat_ulong_t __user *argp) -{ - compat_ulong_t tmp; - - if (get_user(tmp, argp)) - return -EFAULT; - if (tmp == BRCTL_GET_VERSION) - return BRCTL_VERSION + 1; - return -EINVAL; -} - -static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, - unsigned int cmd, unsigned long arg) -{ - void __user *argp = compat_ptr(arg); - struct sock *sk = sock->sk; - struct net *net = sock_net(sk); - - if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) - return siocdevprivate_ioctl(net, cmd, argp); - - switch (cmd) { - case SIOCSIFBR: - case SIOCGIFBR: - return old_bridge_ioctl(argp); - case SIOCGIFNAME: - return dev_ifname32(net, argp); - case SIOCGIFCONF: - return dev_ifconf(net, argp); - case SIOCETHTOOL: - return ethtool_ioctl(net, argp); - case SIOCWANDEV: - return compat_siocwandev(net, argp); - case SIOCGIFMAP: - case SIOCSIFMAP: - return compat_sioc_ifmap(net, cmd, argp); - case SIOCBONDENSLAVE: - case SIOCBONDRELEASE: - case SIOCBONDSETHWADDR: - case SIOCBONDSLAVEINFOQUERY: - case SIOCBONDINFOQUERY: - case SIOCBONDCHANGEACTIVE: - return bond_ioctl(net, cmd, argp); - case SIOCADDRT: - case SIOCDELRT: - return routing_ioctl(net, sock, cmd, argp); - case SIOCGSTAMP: - return do_siocgstamp(net, sock, cmd, argp); - case SIOCGSTAMPNS: - return do_siocgstampns(net, sock, cmd, argp); - case SIOCSHWTSTAMP: - return compat_siocshwtstamp(net, argp); - - case FIOSETOWN: - case SIOCSPGRP: - case FIOGETOWN: - case SIOCGPGRP: - case SIOCBRADDBR: - case SIOCBRDELBR: - case SIOCGIFVLAN: - case SIOCSIFVLAN: - case SIOCADDDLCI: - case SIOCDELDLCI: - return sock_ioctl(file, cmd, arg); - - case SIOCGIFFLAGS: - case SIOCSIFFLAGS: - case SIOCGIFMETRIC: - case SIOCSIFMETRIC: - case SIOCGIFMTU: - case SIOCSIFMTU: - case SIOCGIFMEM: - case SIOCSIFMEM: - case SIOCGIFHWADDR: - case SIOCSIFHWADDR: - case SIOCADDMULTI: - case SIOCDELMULTI: - case SIOCGIFINDEX: - case SIOCGIFADDR: - case SIOCSIFADDR: - case SIOCSIFHWBROADCAST: - case SIOCDIFADDR: - case SIOCGIFBRDADDR: - case SIOCSIFBRDADDR: - case SIOCGIFDSTADDR: - case SIOCSIFDSTADDR: - case SIOCGIFNETMASK: - case SIOCSIFNETMASK: - case SIOCSIFPFLAGS: - case SIOCGIFPFLAGS: - case SIOCGIFTXQLEN: - case SIOCSIFTXQLEN: - case SIOCBRADDIF: - case SIOCBRDELIF: - case SIOCSIFNAME: - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return dev_ifsioc(net, sock, cmd, argp); - - case SIOCSARP: - case SIOCGARP: - case SIOCDARP: - case SIOCATMARK: - return sock_do_ioctl(net, sock, cmd, arg); - } - - /* Prevent warning from compat_sys_ioctl, these always - * result in -EINVAL in the native case anyway. */ - switch (cmd) { - case SIOCRTMSG: - case SIOCGIFCOUNT: - case SIOCSRARP: - case SIOCGRARP: - case SIOCDRARP: - case SIOCSIFLINK: - case SIOCGIFSLAVE: - case SIOCSIFSLAVE: - return -EINVAL; - } - - return -ENOIOCTLCMD; -} - static long compat_sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) { @@ -3040,9 +2477,6 @@ static long compat_sock_ioctl(struct file *file, unsigned cmd, (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) ret = compat_wext_handle_ioctl(net, cmd, arg); - if (ret == -ENOIOCTLCMD) - ret = compat_sock_ioctl_trans(file, sock, cmd, arg); - return ret; } #endif diff --git a/trunk/net/sunrpc/svcsock.c b/trunk/net/sunrpc/svcsock.c index 870929e08e5d..c2a17876defd 100644 --- a/trunk/net/sunrpc/svcsock.c +++ b/trunk/net/sunrpc/svcsock.c @@ -111,7 +111,7 @@ static void svc_release_skb(struct svc_rqst *rqstp) rqstp->rq_xprt_ctxt = NULL; dprintk("svc: service %p, releasing skb %p\n", rqstp, skb); - skb_free_datagram_locked(svsk->sk_sk, skb); + skb_free_datagram(svsk->sk_sk, skb); } } @@ -578,7 +578,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) "svc: received unknown control message %d/%d; " "dropping RPC reply datagram\n", cmh->cmsg_level, cmh->cmsg_type); - skb_free_datagram_locked(svsk->sk_sk, skb); + skb_free_datagram(svsk->sk_sk, skb); return 0; } @@ -588,18 +588,18 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) if (csum_partial_copy_to_xdr(&rqstp->rq_arg, skb)) { local_bh_enable(); /* checksum error */ - skb_free_datagram_locked(svsk->sk_sk, skb); + skb_free_datagram(svsk->sk_sk, skb); return 0; } local_bh_enable(); - skb_free_datagram_locked(svsk->sk_sk, skb); + skb_free_datagram(svsk->sk_sk, skb); } else { /* we can use it in-place */ rqstp->rq_arg.head[0].iov_base = skb->data + sizeof(struct udphdr); rqstp->rq_arg.head[0].iov_len = len; if (skb_checksum_complete(skb)) { - skb_free_datagram_locked(svsk->sk_sk, skb); + skb_free_datagram(svsk->sk_sk, skb); return 0; } rqstp->rq_xprt_ctxt = skb; diff --git a/trunk/net/tipc/socket.c b/trunk/net/tipc/socket.c index d00c2119faf3..e6d9abf7440e 100644 --- a/trunk/net/tipc/socket.c +++ b/trunk/net/tipc/socket.c @@ -177,7 +177,6 @@ static void reject_rx_queue(struct sock *sk) * @net: network namespace (must be default network) * @sock: pre-allocated socket structure * @protocol: protocol indicator (must be 0) - * @kern: caused by kernel or by userspace? * * This routine creates additional data structures used by the TIPC socket, * initializes them, and links them together. @@ -185,8 +184,7 @@ static void reject_rx_queue(struct sock *sk) * Returns 0 on success, errno otherwise */ -static int tipc_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int tipc_create(struct net *net, struct socket *sock, int protocol) { const struct proto_ops *ops; socket_state state; @@ -1530,7 +1528,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) buf = skb_peek(&sk->sk_receive_queue); - res = tipc_create(sock_net(sock->sk), new_sock, 0, 0); + res = tipc_create(sock_net(sock->sk), new_sock, 0); if (!res) { struct sock *new_sk = new_sock->sk; struct tipc_sock *new_tsock = tipc_sk(new_sk); diff --git a/trunk/net/unix/af_unix.c b/trunk/net/unix/af_unix.c index 7553ea6edd8f..3291902f0b88 100644 --- a/trunk/net/unix/af_unix.c +++ b/trunk/net/unix/af_unix.c @@ -621,8 +621,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock) return sk; } -static int unix_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int unix_create(struct net *net, struct socket *sock, int protocol) { if (protocol && protocol != PF_UNIX) return -EPROTONOSUPPORT; @@ -1259,7 +1258,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_ { struct sock *sk = sock->sk; struct unix_sock *u; - DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr); + struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; int err = 0; if (peer) { diff --git a/trunk/net/wimax/op-msg.c b/trunk/net/wimax/op-msg.c index d3bfb6ef13ae..d631a17186bc 100644 --- a/trunk/net/wimax/op-msg.c +++ b/trunk/net/wimax/op-msg.c @@ -388,8 +388,6 @@ int wimax_gnl_doit_msg_from_user(struct sk_buff *skb, struct genl_info *info) } mutex_lock(&wimax_dev->mutex); result = wimax_dev_is_ready(wimax_dev); - if (result == -ENOMEDIUM) - result = 0; if (result < 0) goto error_not_ready; result = -ENOSYS; diff --git a/trunk/net/wimax/op-rfkill.c b/trunk/net/wimax/op-rfkill.c index 94d339c345d2..70ef4df863b9 100644 --- a/trunk/net/wimax/op-rfkill.c +++ b/trunk/net/wimax/op-rfkill.c @@ -305,15 +305,8 @@ int wimax_rfkill(struct wimax_dev *wimax_dev, enum wimax_rf_state state) d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state); mutex_lock(&wimax_dev->mutex); result = wimax_dev_is_ready(wimax_dev); - if (result < 0) { - /* While initializing, < 1.4.3 wimax-tools versions use - * this call to check if the device is a valid WiMAX - * device; so we allow it to proceed always, - * considering the radios are all off. */ - if (result == -ENOMEDIUM && state == WIMAX_RF_QUERY) - result = WIMAX_RF_OFF << 1 | WIMAX_RF_OFF; + if (result < 0) goto error_not_ready; - } switch (state) { case WIMAX_RF_ON: case WIMAX_RF_OFF: @@ -362,7 +355,6 @@ int wimax_rfkill_add(struct wimax_dev *wimax_dev) wimax_dev->rfkill = rfkill; - rfkill_init_sw_state(rfkill, 1); result = rfkill_register(wimax_dev->rfkill); if (result < 0) goto error_rfkill_register; diff --git a/trunk/net/wimax/stack.c b/trunk/net/wimax/stack.c index c8866412f830..79fb7d7c640f 100644 --- a/trunk/net/wimax/stack.c +++ b/trunk/net/wimax/stack.c @@ -60,14 +60,6 @@ #define D_SUBMODULE stack #include "debug-levels.h" -static char wimax_debug_params[128]; -module_param_string(debug, wimax_debug_params, sizeof(wimax_debug_params), - 0644); -MODULE_PARM_DESC(debug, - "String of space-separated NAME:VALUE pairs, where NAMEs " - "are the different debug submodules and VALUE are the " - "initial debug value to set."); - /* * Authoritative source for the RE_STATE_CHANGE attribute policy * @@ -570,9 +562,6 @@ int __init wimax_subsys_init(void) int result, cnt; d_fnstart(4, NULL, "()\n"); - d_parse_params(D_LEVEL, D_LEVEL_SIZE, wimax_debug_params, - "wimax.debug"); - snprintf(wimax_gnl_family.name, sizeof(wimax_gnl_family.name), "WiMAX"); result = genl_register_family(&wimax_gnl_family); diff --git a/trunk/net/wireless/core.c b/trunk/net/wireless/core.c index 02835172b227..07252967be9c 100644 --- a/trunk/net/wireless/core.c +++ b/trunk/net/wireless/core.c @@ -546,7 +546,7 @@ void wiphy_unregister(struct wiphy *wiphy) * First remove the hardware from everywhere, this makes * it impossible to find from userspace. */ - debugfs_remove_recursive(rdev->wiphy.debugfsdir); + cfg80211_debugfs_rdev_del(rdev); list_del(&rdev->list); /* @@ -569,6 +569,7 @@ void wiphy_unregister(struct wiphy *wiphy) cfg80211_rdev_list_generation++; device_del(&rdev->wiphy.dev); + debugfs_remove(rdev->wiphy.debugfsdir); mutex_unlock(&cfg80211_mutex); diff --git a/trunk/net/wireless/core.h b/trunk/net/wireless/core.h index 5aeebb9085f8..68b321997d4c 100644 --- a/trunk/net/wireless/core.h +++ b/trunk/net/wireless/core.h @@ -72,6 +72,17 @@ struct cfg80211_registered_device { /* current channel */ struct ieee80211_channel *channel; +#ifdef CONFIG_CFG80211_DEBUGFS + /* Debugfs entries */ + struct wiphy_debugfsdentries { + struct dentry *rts_threshold; + struct dentry *fragmentation_threshold; + struct dentry *short_retry_limit; + struct dentry *long_retry_limit; + struct dentry *ht40allow_map; + } debugfs; +#endif + /* must be last because of the way we do wiphy_priv(), * and it should at least be aligned to NETDEV_ALIGN */ struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); diff --git a/trunk/net/wireless/debugfs.c b/trunk/net/wireless/debugfs.c index 2e4895615037..13d93d84f902 100644 --- a/trunk/net/wireless/debugfs.c +++ b/trunk/net/wireless/debugfs.c @@ -104,7 +104,11 @@ static const struct file_operations ht40allow_map_ops = { }; #define DEBUGFS_ADD(name) \ - debugfs_create_file(#name, S_IRUGO, phyd, &rdev->wiphy, &name## _ops); + rdev->debugfs.name = debugfs_create_file(#name, S_IRUGO, phyd, \ + &rdev->wiphy, &name## _ops); +#define DEBUGFS_DEL(name) \ + debugfs_remove(rdev->debugfs.name); \ + rdev->debugfs.name = NULL; void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev) { @@ -116,3 +120,12 @@ void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev) DEBUGFS_ADD(long_retry_limit); DEBUGFS_ADD(ht40allow_map); } + +void cfg80211_debugfs_rdev_del(struct cfg80211_registered_device *rdev) +{ + DEBUGFS_DEL(rts_threshold); + DEBUGFS_DEL(fragmentation_threshold); + DEBUGFS_DEL(short_retry_limit); + DEBUGFS_DEL(long_retry_limit); + DEBUGFS_DEL(ht40allow_map); +} diff --git a/trunk/net/wireless/debugfs.h b/trunk/net/wireless/debugfs.h index 74fdd3811427..6419b6d6ce3e 100644 --- a/trunk/net/wireless/debugfs.h +++ b/trunk/net/wireless/debugfs.h @@ -3,9 +3,12 @@ #ifdef CONFIG_CFG80211_DEBUGFS void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev); +void cfg80211_debugfs_rdev_del(struct cfg80211_registered_device *rdev); #else static inline void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev) {} +static inline +void cfg80211_debugfs_rdev_del(struct cfg80211_registered_device *rdev) {} #endif #endif /* __CFG80211_DEBUGFS_H */ diff --git a/trunk/net/wireless/mlme.c b/trunk/net/wireless/mlme.c index 2610b746effa..83c2a288dc63 100644 --- a/trunk/net/wireless/mlme.c +++ b/trunk/net/wireless/mlme.c @@ -62,6 +62,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) u8 *ie = mgmt->u.assoc_resp.variable; int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); struct cfg80211_internal_bss *bss = NULL; + bool need_connect_result = true; wdev_lock(wdev); @@ -96,6 +97,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) WARN_ON(!bss); } else if (wdev->conn) { cfg80211_sme_failed_assoc(wdev); + need_connect_result = false; /* * do not call connect_result() now because the * sme will schedule work that does it later. diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index 8ed62b6c172b..f48394126bf9 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -2988,6 +2988,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) goto out; } + request->n_channels = n_channels; if (n_ssids) request->ssids = (void *)&request->channels[n_channels]; request->n_ssids = n_ssids; @@ -2998,53 +2999,32 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) request->ie = (void *)(request->channels + n_channels); } - i = 0; if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { /* user specified, bail out if channel not found */ + request->n_channels = n_channels; + i = 0; nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) { - struct ieee80211_channel *chan; - - chan = ieee80211_get_channel(wiphy, nla_get_u32(attr)); - - if (!chan) { + request->channels[i] = ieee80211_get_channel(wiphy, nla_get_u32(attr)); + if (!request->channels[i]) { err = -EINVAL; goto out_free; } - - /* ignore disabled channels */ - if (chan->flags & IEEE80211_CHAN_DISABLED) - continue; - - request->channels[i] = chan; i++; } } else { /* all channels */ + i = 0; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { int j; if (!wiphy->bands[band]) continue; for (j = 0; j < wiphy->bands[band]->n_channels; j++) { - struct ieee80211_channel *chan; - - chan = &wiphy->bands[band]->channels[j]; - - if (chan->flags & IEEE80211_CHAN_DISABLED) - continue; - - request->channels[i] = chan; + request->channels[i] = &wiphy->bands[band]->channels[j]; i++; } } } - if (!i) { - err = -EINVAL; - goto out_free; - } - - request->n_channels = i; - i = 0; if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { diff --git a/trunk/net/wireless/scan.c b/trunk/net/wireless/scan.c index e2d344ff6745..2e8c515f3c5c 100644 --- a/trunk/net/wireless/scan.c +++ b/trunk/net/wireless/scan.c @@ -650,15 +650,9 @@ int cfg80211_wext_siwscan(struct net_device *dev, i = 0; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { int j; - if (!wiphy->bands[band]) continue; - for (j = 0; j < wiphy->bands[band]->n_channels; j++) { - /* ignore disabled channels */ - if (wiphy->bands[band]->channels[j].flags & - IEEE80211_CHAN_DISABLED) - continue; /* If we have a wireless request structure and the * wireless request specifies frequencies, then search diff --git a/trunk/net/wireless/sme.c b/trunk/net/wireless/sme.c index 0115d07d2c1a..98a3b7efac4c 100644 --- a/trunk/net/wireless/sme.c +++ b/trunk/net/wireless/sme.c @@ -165,7 +165,7 @@ void cfg80211_conn_work(struct work_struct *work) struct cfg80211_registered_device *rdev = container_of(work, struct cfg80211_registered_device, conn_work); struct wireless_dev *wdev; - u8 bssid_buf[ETH_ALEN], *bssid = NULL; + u8 bssid[ETH_ALEN]; rtnl_lock(); cfg80211_lock_rdev(rdev); @@ -181,10 +181,7 @@ void cfg80211_conn_work(struct work_struct *work) wdev_unlock(wdev); continue; } - if (wdev->conn->params.bssid) { - memcpy(bssid_buf, wdev->conn->params.bssid, ETH_ALEN); - bssid = bssid_buf; - } + memcpy(bssid, wdev->conn->params.bssid, ETH_ALEN); if (cfg80211_conn_do_work(wdev)) __cfg80211_connect_result( wdev->netdev, bssid, diff --git a/trunk/net/wireless/wext-compat.c b/trunk/net/wireless/wext-compat.c index 41abcbdc5fb9..561a45cf2a6a 100644 --- a/trunk/net/wireless/wext-compat.c +++ b/trunk/net/wireless/wext-compat.c @@ -904,6 +904,8 @@ static int cfg80211_set_auth_alg(struct wireless_dev *wdev, static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions) { + wdev->wext.connect.crypto.wpa_versions = 0; + if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA | IW_AUTH_WPA_VERSION_WPA2| IW_AUTH_WPA_VERSION_DISABLED)) @@ -931,6 +933,8 @@ static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions) static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher) { + wdev->wext.connect.crypto.cipher_group = 0; + if (cipher & IW_AUTH_CIPHER_WEP40) wdev->wext.connect.crypto.cipher_group = WLAN_CIPHER_SUITE_WEP40; @@ -946,8 +950,6 @@ static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher) else if (cipher & IW_AUTH_CIPHER_AES_CMAC) wdev->wext.connect.crypto.cipher_group = WLAN_CIPHER_SUITE_AES_CMAC; - else if (cipher & IW_AUTH_CIPHER_NONE) - wdev->wext.connect.crypto.cipher_group = 0; else return -EINVAL; diff --git a/trunk/net/x25/af_x25.c b/trunk/net/x25/af_x25.c index 39ce03e07d18..e19d811788a5 100644 --- a/trunk/net/x25/af_x25.c +++ b/trunk/net/x25/af_x25.c @@ -415,7 +415,6 @@ static int x25_setsockopt(struct socket *sock, int level, int optname, struct sock *sk = sock->sk; int rc = -ENOPROTOOPT; - lock_kernel(); if (level != SOL_X25 || optname != X25_QBITINCL) goto out; @@ -430,7 +429,6 @@ static int x25_setsockopt(struct socket *sock, int level, int optname, x25_sk(sk)->qbitincl = !!opt; rc = 0; out: - unlock_kernel(); return rc; } @@ -440,7 +438,6 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, struct sock *sk = sock->sk; int val, len, rc = -ENOPROTOOPT; - lock_kernel(); if (level != SOL_X25 || optname != X25_QBITINCL) goto out; @@ -461,7 +458,6 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, val = x25_sk(sk)->qbitincl; rc = copy_to_user(optval, &val, len) ? -EFAULT : 0; out: - unlock_kernel(); return rc; } @@ -470,14 +466,12 @@ static int x25_listen(struct socket *sock, int backlog) struct sock *sk = sock->sk; int rc = -EOPNOTSUPP; - lock_kernel(); if (sk->sk_state != TCP_LISTEN) { memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN); sk->sk_max_ack_backlog = backlog; sk->sk_state = TCP_LISTEN; rc = 0; } - unlock_kernel(); return rc; } @@ -507,8 +501,7 @@ static struct sock *x25_alloc_socket(struct net *net) return sk; } -static int x25_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int x25_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; struct x25_sock *x25; @@ -604,7 +597,6 @@ static int x25_release(struct socket *sock) struct sock *sk = sock->sk; struct x25_sock *x25; - lock_kernel(); if (!sk) goto out; @@ -635,7 +627,6 @@ static int x25_release(struct socket *sock) sock_orphan(sk); out: - unlock_kernel(); return 0; } @@ -643,23 +634,18 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; - int rc = 0; - lock_kernel(); if (!sock_flag(sk, SOCK_ZAPPED) || addr_len != sizeof(struct sockaddr_x25) || - addr->sx25_family != AF_X25) { - rc = -EINVAL; - goto out; - } + addr->sx25_family != AF_X25) + return -EINVAL; x25_sk(sk)->source_addr = addr->sx25_addr; x25_insert_socket(sk); sock_reset_flag(sk, SOCK_ZAPPED); SOCK_DEBUG(sk, "x25_bind: socket is bound\n"); -out: - unlock_kernel(); - return rc; + + return 0; } static int x25_wait_for_connection_establishment(struct sock *sk) @@ -700,7 +686,6 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, struct x25_route *rt; int rc = 0; - lock_kernel(); lock_sock(sk); if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { sock->state = SS_CONNECTED; @@ -778,7 +763,6 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, x25_route_put(rt); out: release_sock(sk); - unlock_kernel(); return rc; } @@ -818,7 +802,6 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) struct sk_buff *skb; int rc = -EINVAL; - lock_kernel(); if (!sk || sk->sk_state != TCP_LISTEN) goto out; @@ -846,7 +829,6 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) out2: release_sock(sk); out: - unlock_kernel(); return rc; } @@ -856,14 +838,10 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr, struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr; struct sock *sk = sock->sk; struct x25_sock *x25 = x25_sk(sk); - int rc = 0; - lock_kernel(); if (peer) { - if (sk->sk_state != TCP_ESTABLISHED) { - rc = -ENOTCONN; - goto out; - } + if (sk->sk_state != TCP_ESTABLISHED) + return -ENOTCONN; sx25->sx25_addr = x25->dest_addr; } else sx25->sx25_addr = x25->source_addr; @@ -871,21 +849,7 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr, sx25->sx25_family = AF_X25; *uaddr_len = sizeof(*sx25); -out: - unlock_kernel(); - return rc; -} - -static unsigned int x25_datagram_poll(struct file *file, struct socket *sock, - poll_table *wait) -{ - int rc; - - lock_kernel(); - rc = datagram_poll(file, sock, wait); - unlock_kernel(); - - return rc; + return 0; } int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, @@ -1038,7 +1002,6 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, size_t size; int qbit = 0, rc = -EINVAL; - lock_kernel(); if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT)) goto out; @@ -1203,7 +1166,6 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, release_sock(sk); rc = len; out: - unlock_kernel(); return rc; out_kfree_skb: kfree_skb(skb); @@ -1224,7 +1186,6 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, unsigned char *asmptr; int rc = -ENOTCONN; - lock_kernel(); /* * This works for seqpacket too. The receiver has ordered the queue for * us! We do one quick check first though @@ -1298,7 +1259,6 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, out_free_dgram: skb_free_datagram(sk, skb); out: - unlock_kernel(); return rc; } @@ -1310,7 +1270,6 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) void __user *argp = (void __user *)arg; int rc; - lock_kernel(); switch (cmd) { case TIOCOUTQ: { int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); @@ -1513,7 +1472,6 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) rc = -ENOIOCTLCMD; break; } - unlock_kernel(); return rc; } @@ -1584,19 +1542,15 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, break; case SIOCGSTAMP: rc = -EINVAL; - lock_kernel(); if (sk) rc = compat_sock_get_timestamp(sk, (struct timeval __user*)argp); - unlock_kernel(); break; case SIOCGSTAMPNS: rc = -EINVAL; - lock_kernel(); if (sk) rc = compat_sock_get_timestampns(sk, (struct timespec __user*)argp); - unlock_kernel(); break; case SIOCGIFADDR: case SIOCSIFADDR: @@ -1615,22 +1569,16 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, rc = -EPERM; if (!capable(CAP_NET_ADMIN)) break; - lock_kernel(); rc = x25_route_ioctl(cmd, argp); - unlock_kernel(); break; case SIOCX25GSUBSCRIP: - lock_kernel(); rc = compat_x25_subscr_ioctl(cmd, argp); - unlock_kernel(); break; case SIOCX25SSUBSCRIP: rc = -EPERM; if (!capable(CAP_NET_ADMIN)) break; - lock_kernel(); rc = compat_x25_subscr_ioctl(cmd, argp); - unlock_kernel(); break; case SIOCX25GFACILITIES: case SIOCX25SFACILITIES: @@ -1652,7 +1600,7 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, } #endif -static const struct proto_ops x25_proto_ops = { +static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { .family = AF_X25, .owner = THIS_MODULE, .release = x25_release, @@ -1661,7 +1609,7 @@ static const struct proto_ops x25_proto_ops = { .socketpair = sock_no_socketpair, .accept = x25_accept, .getname = x25_getname, - .poll = x25_datagram_poll, + .poll = datagram_poll, .ioctl = x25_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = compat_x25_ioctl, @@ -1676,6 +1624,8 @@ static const struct proto_ops x25_proto_ops = { .sendpage = sock_no_sendpage, }; +SOCKOPS_WRAP(x25_proto, AF_X25); + static struct packet_type x25_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_X25), .func = x25_lapb_receive_frame, diff --git a/trunk/net/xfrm/xfrm_state.c b/trunk/net/xfrm/xfrm_state.c index e9ac0cec0877..f2f7c638083e 100644 --- a/trunk/net/xfrm/xfrm_state.c +++ b/trunk/net/xfrm/xfrm_state.c @@ -21,9 +21,6 @@ #include #include #include -#include -#include -#include #include "xfrm_hash.h" @@ -355,7 +352,7 @@ static void xfrm_put_mode(struct xfrm_mode *mode) static void xfrm_state_gc_destroy(struct xfrm_state *x) { - tasklet_hrtimer_cancel(&x->mtimer); + del_timer_sync(&x->timer); del_timer_sync(&x->rtimer); kfree(x->aalg); kfree(x->ealg); @@ -401,10 +398,9 @@ static inline unsigned long make_jiffies(long secs) return secs*HZ; } -static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) +static void xfrm_timer_handler(unsigned long data) { - struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer); - struct xfrm_state *x = container_of(thr, struct xfrm_state, mtimer); + struct xfrm_state *x = (struct xfrm_state*)data; struct net *net = xs_net(x); unsigned long now = get_seconds(); long next = LONG_MAX; @@ -455,9 +451,8 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) if (warn) km_state_expired(x, 0, 0); resched: - if (next != LONG_MAX){ - tasklet_hrtimer_start(&x->mtimer, ktime_set(next, 0), HRTIMER_MODE_REL); - } + if (next != LONG_MAX) + mod_timer(&x->timer, jiffies + make_jiffies(next)); goto out; @@ -479,7 +474,6 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) out: spin_unlock(&x->lock); - return HRTIMER_NORESTART; } static void xfrm_replay_timer_handler(unsigned long data); @@ -498,7 +492,7 @@ struct xfrm_state *xfrm_state_alloc(struct net *net) INIT_HLIST_NODE(&x->bydst); INIT_HLIST_NODE(&x->bysrc); INIT_HLIST_NODE(&x->byspi); - tasklet_hrtimer_init(&x->mtimer, xfrm_timer_handler, CLOCK_REALTIME, HRTIMER_MODE_ABS); + setup_timer(&x->timer, xfrm_timer_handler, (unsigned long)x); setup_timer(&x->rtimer, xfrm_replay_timer_handler, (unsigned long)x); x->curlft.add_time = get_seconds(); @@ -849,7 +843,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); } x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; - tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL); + x->timer.expires = jiffies + net->xfrm.sysctl_acq_expires*HZ; + add_timer(&x->timer); net->xfrm.state_num++; xfrm_hash_grow_check(net, x->bydst.next != NULL); } else { @@ -926,7 +921,7 @@ static void __xfrm_state_insert(struct xfrm_state *x) hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); } - tasklet_hrtimer_start(&x->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL); + mod_timer(&x->timer, jiffies + HZ); if (x->replay_maxage) mod_timer(&x->rtimer, jiffies + x->replay_maxage); @@ -1024,7 +1019,8 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family x->props.reqid = reqid; x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; xfrm_state_hold(x); - tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL); + x->timer.expires = jiffies + net->xfrm.sysctl_acq_expires*HZ; + add_timer(&x->timer); list_add(&x->km.all, &net->xfrm.state_all); hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); h = xfrm_src_hash(net, daddr, saddr, family); @@ -1304,7 +1300,7 @@ int xfrm_state_update(struct xfrm_state *x) memcpy(&x1->lft, &x->lft, sizeof(x1->lft)); x1->km.dying = 0; - tasklet_hrtimer_start(&x1->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL); + mod_timer(&x1->timer, jiffies + HZ); if (x1->curlft.use_time) xfrm_state_check_expire(x1); @@ -1329,7 +1325,7 @@ int xfrm_state_check_expire(struct xfrm_state *x) if (x->curlft.bytes >= x->lft.hard_byte_limit || x->curlft.packets >= x->lft.hard_packet_limit) { x->km.state = XFRM_STATE_EXPIRED; - tasklet_hrtimer_start(&x->mtimer, ktime_set(0,0), HRTIMER_MODE_REL); + mod_timer(&x->timer, jiffies); return -EINVAL; }