2011-10-11 17:41:21 -07:00
/*
* Marvell Wireless LAN device driver : PCIE specific handling
*
2014-06-19 21:38:57 -07:00
* Copyright ( C ) 2011 - 2014 , Marvell International Ltd .
2011-10-11 17:41:21 -07:00
*
* This software file ( the " File " ) is distributed by Marvell International
* Ltd . under the terms of the GNU General Public License Version 2 , June 1991
* ( the " License " ) . You may use , redistribute and / or modify this File in
* accordance with the terms and conditions of the License , a copy of which
* is available by writing to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA or on the
* worldwide web at http : //www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* THE FILE IS DISTRIBUTED AS - IS , WITHOUT WARRANTY OF ANY KIND , AND THE
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
* ARE EXPRESSLY DISCLAIMED . The License provides additional details about
* this warranty disclaimer .
*/
# include <linux/firmware.h>
# include "decl.h"
# include "ioctl.h"
# include "util.h"
# include "fw.h"
# include "main.h"
# include "wmm.h"
# include "11n.h"
# include "pcie.h"
# define PCIE_VERSION "1.0"
# define DRV_NAME "Marvell mwifiex PCIe"
static u8 user_rmmod ;
static struct mwifiex_if_ops pcie_ops ;
static struct semaphore add_remove_card_sem ;
2014-06-19 21:38:52 -07:00
static struct memory_type_mapping mem_type_mapping_tbl [ ] = {
{ " ITCM " , NULL , 0 , 0xF0 } ,
{ " DTCM " , NULL , 0 , 0xF1 } ,
{ " SQRAM " , NULL , 0 , 0xF2 } ,
{ " IRAM " , NULL , 0 , 0xF3 } ,
2014-09-18 07:18:50 -04:00
{ " APU " , NULL , 0 , 0xF4 } ,
{ " CIU " , NULL , 0 , 0xF5 } ,
{ " ICU " , NULL , 0 , 0xF6 } ,
{ " MAC " , NULL , 0 , 0xF7 } ,
2014-06-19 21:38:52 -07:00
} ;
2013-01-03 21:21:30 -08:00
static int
mwifiex_map_pci_memory ( struct mwifiex_adapter * adapter , struct sk_buff * skb ,
2014-02-07 16:25:50 -08:00
size_t size , int flags )
2011-10-11 17:41:21 -07:00
{
2013-01-03 21:21:30 -08:00
struct pcie_service_card * card = adapter - > card ;
2014-02-07 16:25:50 -08:00
struct mwifiex_dma_mapping mapping ;
2011-10-11 17:41:21 -07:00
2014-02-07 16:25:50 -08:00
mapping . addr = pci_map_single ( card - > dev , skb - > data , size , flags ) ;
if ( pci_dma_mapping_error ( card - > dev , mapping . addr ) ) {
2013-01-03 21:21:30 -08:00
dev_err ( adapter - > dev , " failed to map pci memory! \n " ) ;
return - 1 ;
}
2014-02-07 16:25:50 -08:00
mapping . len = size ;
2014-06-06 19:37:10 -07:00
mwifiex_store_mapping ( skb , & mapping ) ;
2013-01-03 21:21:30 -08:00
return 0 ;
2011-10-11 17:41:21 -07:00
}
2014-02-07 16:25:50 -08:00
static void mwifiex_unmap_pci_memory ( struct mwifiex_adapter * adapter ,
struct sk_buff * skb , int flags )
{
struct pcie_service_card * card = adapter - > card ;
struct mwifiex_dma_mapping mapping ;
2014-06-06 19:37:10 -07:00
mwifiex_get_mapping ( skb , & mapping ) ;
2014-02-07 16:25:50 -08:00
pci_unmap_single ( card - > dev , mapping . addr , mapping . len , flags ) ;
}
2011-10-11 17:41:21 -07:00
/*
* This function reads sleep cookie and checks if FW is ready
*/
static bool mwifiex_pcie_ok_to_access_hw ( struct mwifiex_adapter * adapter )
{
u32 * cookie_addr ;
struct pcie_service_card * card = adapter - > card ;
2013-02-12 14:38:32 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
if ( ! reg - > sleep_cookie )
return true ;
2011-10-11 17:41:21 -07:00
2013-01-03 21:21:30 -08:00
if ( card - > sleep_cookie_vbase ) {
cookie_addr = ( u32 * ) card - > sleep_cookie_vbase ;
2011-10-11 17:41:21 -07:00
dev_dbg ( adapter - > dev , " info: ACCESS_HW: sleep cookie=0x%x \n " ,
* cookie_addr ) ;
if ( * cookie_addr = = FW_AWAKE_COOKIE )
return true ;
}
return false ;
}
2013-07-03 10:47:10 -06:00
# ifdef CONFIG_PM_SLEEP
2013-03-04 16:27:53 -08:00
/*
* Kernel needs to suspend all functions separately . Therefore all
* registered functions must have drivers with suspend and resume
* methods . Failing that the kernel simply removes the whole card .
*
* If already not suspended , this function allocates and sends a host
* sleep activate request to the firmware and turns off the traffic .
*/
2013-07-03 10:47:10 -06:00
static int mwifiex_pcie_suspend ( struct device * dev )
2013-03-04 16:27:53 -08:00
{
struct mwifiex_adapter * adapter ;
struct pcie_service_card * card ;
int hs_actived ;
2013-07-03 10:47:10 -06:00
struct pci_dev * pdev = to_pci_dev ( dev ) ;
2013-03-04 16:27:53 -08:00
if ( pdev ) {
2013-09-09 14:26:51 +09:00
card = pci_get_drvdata ( pdev ) ;
2013-03-04 16:27:53 -08:00
if ( ! card | | ! card - > adapter ) {
pr_err ( " Card or adapter structure is not valid \n " ) ;
return 0 ;
}
} else {
pr_err ( " PCIE device is not specified \n " ) ;
return 0 ;
}
adapter = card - > adapter ;
hs_actived = mwifiex_enable_hs ( adapter ) ;
/* Indicate device suspended */
adapter - > is_suspended = true ;
2014-03-25 19:01:20 -07:00
adapter - > hs_enabling = false ;
2013-03-04 16:27:53 -08:00
return 0 ;
}
/*
* Kernel needs to suspend all functions separately . Therefore all
* registered functions must have drivers with suspend and resume
* methods . Failing that the kernel simply removes the whole card .
*
* If already not resumed , this function turns on the traffic and
* sends a host sleep cancel request to the firmware .
*/
2013-07-03 10:47:10 -06:00
static int mwifiex_pcie_resume ( struct device * dev )
2013-03-04 16:27:53 -08:00
{
struct mwifiex_adapter * adapter ;
struct pcie_service_card * card ;
2013-07-03 10:47:10 -06:00
struct pci_dev * pdev = to_pci_dev ( dev ) ;
2013-03-04 16:27:53 -08:00
if ( pdev ) {
2013-09-09 14:26:51 +09:00
card = pci_get_drvdata ( pdev ) ;
2013-03-04 16:27:53 -08:00
if ( ! card | | ! card - > adapter ) {
pr_err ( " Card or adapter structure is not valid \n " ) ;
return 0 ;
}
} else {
pr_err ( " PCIE device is not specified \n " ) ;
return 0 ;
}
adapter = card - > adapter ;
if ( ! adapter - > is_suspended ) {
dev_warn ( adapter - > dev , " Device already resumed \n " ) ;
return 0 ;
}
adapter - > is_suspended = false ;
mwifiex_cancel_hs ( mwifiex_get_priv ( adapter , MWIFIEX_BSS_ROLE_STA ) ,
MWIFIEX_ASYNC_CMD ) ;
return 0 ;
}
2013-03-04 16:27:54 -08:00
# endif
2013-03-04 16:27:53 -08:00
2011-10-11 17:41:21 -07:00
/*
* This function probes an mwifiex device and registers it . It allocates
* the card structure , enables PCIE function number and initiates the
* device registration and initialization procedure by adding a logical
* interface .
*/
static int mwifiex_pcie_probe ( struct pci_dev * pdev ,
const struct pci_device_id * ent )
{
struct pcie_service_card * card ;
pr_debug ( " info: vendor=0x%4.04X device=0x%4.04X rev=%d \n " ,
2012-03-13 19:22:37 -07:00
pdev - > vendor , pdev - > device , pdev - > revision ) ;
2011-10-11 17:41:21 -07:00
card = kzalloc ( sizeof ( struct pcie_service_card ) , GFP_KERNEL ) ;
2012-01-29 12:56:23 +00:00
if ( ! card )
2011-10-11 17:41:21 -07:00
return - ENOMEM ;
card - > dev = pdev ;
2013-02-08 18:18:06 -08:00
if ( ent - > driver_data ) {
struct mwifiex_pcie_device * data = ( void * ) ent - > driver_data ;
card - > pcie . firmware = data - > firmware ;
card - > pcie . reg = data - > reg ;
card - > pcie . blksz_fw_dl = data - > blksz_fw_dl ;
2014-02-27 19:35:13 -08:00
card - > pcie . tx_buf_size = data - > tx_buf_size ;
2014-06-19 21:38:52 -07:00
card - > pcie . supports_fw_dump = data - > supports_fw_dump ;
2013-02-08 18:18:06 -08:00
}
2011-10-11 17:41:21 -07:00
if ( mwifiex_add_card ( card , & add_remove_card_sem , & pcie_ops ,
MWIFIEX_PCIE ) ) {
pr_err ( " %s failed \n " , __func__ ) ;
kfree ( card ) ;
return - 1 ;
}
return 0 ;
}
/*
* This function removes the interface and frees up the card structure .
*/
static void mwifiex_pcie_remove ( struct pci_dev * pdev )
{
struct pcie_service_card * card ;
struct mwifiex_adapter * adapter ;
2012-03-13 19:22:37 -07:00
struct mwifiex_private * priv ;
2011-10-11 17:41:21 -07:00
card = pci_get_drvdata ( pdev ) ;
if ( ! card )
return ;
adapter = card - > adapter ;
if ( ! adapter | | ! adapter - > priv_num )
return ;
2014-06-19 21:38:52 -07:00
cancel_work_sync ( & adapter - > iface_work ) ;
2011-10-11 17:41:21 -07:00
if ( user_rmmod ) {
2013-07-03 10:47:10 -06:00
# ifdef CONFIG_PM_SLEEP
2011-10-11 17:41:21 -07:00
if ( adapter - > is_suspended )
2013-07-03 10:47:10 -06:00
mwifiex_pcie_resume ( & pdev - > dev ) ;
2011-10-11 17:41:21 -07:00
# endif
2014-02-27 19:35:17 -08:00
mwifiex_deauthenticate_all ( adapter ) ;
2011-10-11 17:41:21 -07:00
2012-03-13 19:22:37 -07:00
priv = mwifiex_get_priv ( adapter , MWIFIEX_BSS_ROLE_ANY ) ;
2011-10-11 17:41:21 -07:00
2012-03-13 19:22:37 -07:00
mwifiex_disable_auto_ds ( priv ) ;
mwifiex_init_shutdown_fw ( priv , MWIFIEX_FUNC_SHUTDOWN ) ;
2011-10-11 17:41:21 -07:00
}
mwifiex_remove_card ( card - > adapter , & add_remove_card_sem ) ;
}
2013-07-22 19:17:47 -07:00
static void mwifiex_pcie_shutdown ( struct pci_dev * pdev )
{
user_rmmod = 1 ;
mwifiex_pcie_remove ( pdev ) ;
return ;
}
2014-08-08 15:56:03 +02:00
static const struct pci_device_id mwifiex_ids [ ] = {
2011-10-11 17:41:21 -07:00
{
PCIE_VENDOR_ID_MARVELL , PCIE_DEVICE_ID_MARVELL_88W8766P ,
PCI_ANY_ID , PCI_ANY_ID , 0 , 0 ,
2013-02-08 18:18:06 -08:00
. driver_data = ( unsigned long ) & mwifiex_pcie8766 ,
2011-10-11 17:41:21 -07:00
} ,
2013-02-08 18:18:09 -08:00
{
PCIE_VENDOR_ID_MARVELL , PCIE_DEVICE_ID_MARVELL_88W8897 ,
PCI_ANY_ID , PCI_ANY_ID , 0 , 0 ,
. driver_data = ( unsigned long ) & mwifiex_pcie8897 ,
} ,
2011-10-11 17:41:21 -07:00
{ } ,
} ;
MODULE_DEVICE_TABLE ( pci , mwifiex_ids ) ;
2013-07-03 10:47:10 -06:00
# ifdef CONFIG_PM_SLEEP
/* Power Management Hooks */
static SIMPLE_DEV_PM_OPS ( mwifiex_pcie_pm_ops , mwifiex_pcie_suspend ,
mwifiex_pcie_resume ) ;
# endif
2011-10-11 17:41:21 -07:00
/* PCI Device Driver */
static struct pci_driver __refdata mwifiex_pcie = {
. name = " mwifiex_pcie " ,
. id_table = mwifiex_ids ,
. probe = mwifiex_pcie_probe ,
. remove = mwifiex_pcie_remove ,
2013-07-03 10:47:10 -06:00
# ifdef CONFIG_PM_SLEEP
. driver = {
. pm = & mwifiex_pcie_pm_ops ,
} ,
2011-10-11 17:41:21 -07:00
# endif
2013-07-22 19:17:47 -07:00
. shutdown = mwifiex_pcie_shutdown ,
2011-10-11 17:41:21 -07:00
} ;
/*
* This function writes data into PCIE card register .
*/
static int mwifiex_write_reg ( struct mwifiex_adapter * adapter , int reg , u32 data )
{
struct pcie_service_card * card = adapter - > card ;
iowrite32 ( data , card - > pci_mmap1 + reg ) ;
return 0 ;
}
/*
* This function reads data from PCIE card register .
*/
static int mwifiex_read_reg ( struct mwifiex_adapter * adapter , int reg , u32 * data )
{
struct pcie_service_card * card = adapter - > card ;
* data = ioread32 ( card - > pci_mmap1 + reg ) ;
return 0 ;
}
2014-06-19 21:38:52 -07:00
/* This function reads u8 data from PCIE card register. */
static int mwifiex_read_reg_byte ( struct mwifiex_adapter * adapter ,
int reg , u8 * data )
{
struct pcie_service_card * card = adapter - > card ;
* data = ioread8 ( card - > pci_mmap1 + reg ) ;
return 0 ;
}
2011-10-11 17:41:21 -07:00
/*
2013-03-22 21:49:07 -07:00
* This function adds delay loop to ensure FW is awake before proceeding .
2011-10-11 17:41:21 -07:00
*/
2013-03-22 21:49:07 -07:00
static void mwifiex_pcie_dev_wakeup_delay ( struct mwifiex_adapter * adapter )
2011-10-11 17:41:21 -07:00
{
int i = 0 ;
2013-03-22 21:49:07 -07:00
while ( mwifiex_pcie_ok_to_access_hw ( adapter ) ) {
2011-10-11 17:41:21 -07:00
i + + ;
2012-03-12 19:35:11 -07:00
usleep_range ( 10 , 20 ) ;
2011-10-11 17:41:21 -07:00
/* 50ms max wait */
2013-02-25 16:01:34 -08:00
if ( i = = 5000 )
2011-10-11 17:41:21 -07:00
break ;
}
2013-03-22 21:49:07 -07:00
return ;
}
2014-03-18 22:19:17 -07:00
static void mwifiex_delay_for_sleep_cookie ( struct mwifiex_adapter * adapter ,
u32 max_delay_loop_cnt )
{
struct pcie_service_card * card = adapter - > card ;
u8 * buffer ;
u32 sleep_cookie , count ;
for ( count = 0 ; count < max_delay_loop_cnt ; count + + ) {
buffer = card - > cmdrsp_buf - > data - INTF_HEADER_LEN ;
sleep_cookie = * ( u32 * ) buffer ;
if ( sleep_cookie = = MWIFIEX_DEF_SLEEP_COOKIE ) {
dev_dbg ( adapter - > dev ,
" sleep cookie found at count %d \n " , count ) ;
break ;
}
usleep_range ( 20 , 30 ) ;
}
if ( count > = max_delay_loop_cnt )
dev_dbg ( adapter - > dev ,
" max count reached while accessing sleep cookie \n " ) ;
}
2013-03-22 21:49:07 -07:00
/* This function wakes up the card by reading fw_status register. */
static int mwifiex_pm_wakeup_card ( struct mwifiex_adapter * adapter )
{
u32 fw_status ;
struct pcie_service_card * card = adapter - > card ;
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
dev_dbg ( adapter - > dev , " event: Wakeup device... \n " ) ;
2013-03-22 21:49:07 -07:00
if ( reg - > sleep_cookie )
mwifiex_pcie_dev_wakeup_delay ( adapter ) ;
/* Reading fw_status register will wakeup device */
if ( mwifiex_read_reg ( adapter , reg - > fw_status , & fw_status ) ) {
dev_warn ( adapter - > dev , " Reading fw_status register failed \n " ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
2013-03-22 21:49:07 -07:00
if ( reg - > sleep_cookie ) {
mwifiex_pcie_dev_wakeup_delay ( adapter ) ;
dev_dbg ( adapter - > dev , " PCIE wakeup: Setting PS_STATE_AWAKE \n " ) ;
adapter - > ps_state = PS_STATE_AWAKE ;
}
2011-10-11 17:41:21 -07:00
return 0 ;
}
/*
* This function is called after the card has woken up .
*
* The card configuration register is reset .
*/
static int mwifiex_pm_wakeup_card_complete ( struct mwifiex_adapter * adapter )
{
dev_dbg ( adapter - > dev , " cmd: Wakeup device completed \n " ) ;
return 0 ;
}
/*
* This function disables the host interrupt .
*
* The host interrupt mask is read , the disable bit is reset and
* written back to the card host interrupt mask register .
*/
static int mwifiex_pcie_disable_host_int ( struct mwifiex_adapter * adapter )
{
if ( mwifiex_pcie_ok_to_access_hw ( adapter ) ) {
if ( mwifiex_write_reg ( adapter , PCIE_HOST_INT_MASK ,
0x00000000 ) ) {
dev_warn ( adapter - > dev , " Disable host interrupt failed \n " ) ;
return - 1 ;
}
}
return 0 ;
}
/*
* This function enables the host interrupt .
*
* The host interrupt enable mask is written to the card
* host interrupt mask register .
*/
static int mwifiex_pcie_enable_host_int ( struct mwifiex_adapter * adapter )
{
if ( mwifiex_pcie_ok_to_access_hw ( adapter ) ) {
/* Simply write the mask to the register */
if ( mwifiex_write_reg ( adapter , PCIE_HOST_INT_MASK ,
HOST_INTR_MASK ) ) {
dev_warn ( adapter - > dev , " Enable host interrupt failed \n " ) ;
return - 1 ;
}
}
return 0 ;
}
/*
2013-02-08 18:18:07 -08:00
* This function initializes TX buffer ring descriptors
*/
static int mwifiex_init_txq_ring ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:09 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2013-02-08 18:18:07 -08:00
struct mwifiex_pcie_buf_desc * desc ;
2013-02-08 18:18:09 -08:00
struct mwifiex_pfu_buf_desc * desc2 ;
2013-02-08 18:18:07 -08:00
int i ;
for ( i = 0 ; i < MWIFIEX_MAX_TXRX_BD ; i + + ) {
card - > tx_buf_list [ i ] = NULL ;
2013-02-08 18:18:09 -08:00
if ( reg - > pfu_enabled ) {
card - > txbd_ring [ i ] = ( void * ) card - > txbd_ring_vbase +
( sizeof ( * desc2 ) * i ) ;
desc2 = card - > txbd_ring [ i ] ;
memset ( desc2 , 0 , sizeof ( * desc2 ) ) ;
} else {
card - > txbd_ring [ i ] = ( void * ) card - > txbd_ring_vbase +
( sizeof ( * desc ) * i ) ;
desc = card - > txbd_ring [ i ] ;
memset ( desc , 0 , sizeof ( * desc ) ) ;
}
2013-02-08 18:18:07 -08:00
}
return 0 ;
}
/* This function initializes RX buffer ring descriptors. Each SKB is allocated
* here and after mapping PCI memory , its physical address is assigned to
* PCIE Rx buffer descriptor ' s physical address .
*/
static int mwifiex_init_rxq_ring ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:09 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2013-02-08 18:18:07 -08:00
struct sk_buff * skb ;
struct mwifiex_pcie_buf_desc * desc ;
2013-02-08 18:18:09 -08:00
struct mwifiex_pfu_buf_desc * desc2 ;
2013-02-08 18:18:07 -08:00
dma_addr_t buf_pa ;
int i ;
for ( i = 0 ; i < MWIFIEX_MAX_TXRX_BD ; i + + ) {
/* Allocate skb here so that firmware can DMA data from it */
skb = dev_alloc_skb ( MWIFIEX_RX_DATA_BUF_SIZE ) ;
if ( ! skb ) {
dev_err ( adapter - > dev ,
" Unable to allocate skb for RX ring. \n " ) ;
kfree ( card - > rxbd_ring_vbase ) ;
return - ENOMEM ;
}
if ( mwifiex_map_pci_memory ( adapter , skb ,
MWIFIEX_RX_DATA_BUF_SIZE ,
PCI_DMA_FROMDEVICE ) )
return - 1 ;
2014-02-07 16:25:50 -08:00
buf_pa = MWIFIEX_SKB_DMA_ADDR ( skb ) ;
2013-02-08 18:18:07 -08:00
dev_dbg ( adapter - > dev ,
" info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x \n " ,
skb , skb - > len , skb - > data , ( u32 ) buf_pa ,
( u32 ) ( ( u64 ) buf_pa > > 32 ) ) ;
card - > rx_buf_list [ i ] = skb ;
2013-02-08 18:18:09 -08:00
if ( reg - > pfu_enabled ) {
card - > rxbd_ring [ i ] = ( void * ) card - > rxbd_ring_vbase +
( sizeof ( * desc2 ) * i ) ;
desc2 = card - > rxbd_ring [ i ] ;
desc2 - > paddr = buf_pa ;
desc2 - > len = ( u16 ) skb - > len ;
desc2 - > frag_len = ( u16 ) skb - > len ;
desc2 - > flags = reg - > ring_flag_eop | reg - > ring_flag_sop ;
desc2 - > offset = 0 ;
} else {
card - > rxbd_ring [ i ] = ( void * ) ( card - > rxbd_ring_vbase +
( sizeof ( * desc ) * i ) ) ;
desc = card - > rxbd_ring [ i ] ;
desc - > paddr = buf_pa ;
desc - > len = ( u16 ) skb - > len ;
desc - > flags = 0 ;
}
2013-02-08 18:18:07 -08:00
}
return 0 ;
}
/* This function initializes event buffer ring descriptors. Each SKB is
* allocated here and after mapping PCI memory , its physical address is assigned
* to PCIE Rx buffer descriptor ' s physical address
*/
static int mwifiex_pcie_init_evt_ring ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:08 -08:00
struct mwifiex_evt_buf_desc * desc ;
2013-02-08 18:18:07 -08:00
struct sk_buff * skb ;
dma_addr_t buf_pa ;
int i ;
for ( i = 0 ; i < MWIFIEX_MAX_EVT_BD ; i + + ) {
/* Allocate skb here so that firmware can DMA data from it */
skb = dev_alloc_skb ( MAX_EVENT_SIZE ) ;
if ( ! skb ) {
dev_err ( adapter - > dev ,
" Unable to allocate skb for EVENT buf. \n " ) ;
kfree ( card - > evtbd_ring_vbase ) ;
return - ENOMEM ;
}
skb_put ( skb , MAX_EVENT_SIZE ) ;
if ( mwifiex_map_pci_memory ( adapter , skb , MAX_EVENT_SIZE ,
PCI_DMA_FROMDEVICE ) )
return - 1 ;
2014-02-07 16:25:50 -08:00
buf_pa = MWIFIEX_SKB_DMA_ADDR ( skb ) ;
2013-02-08 18:18:07 -08:00
dev_dbg ( adapter - > dev ,
" info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x \n " ,
skb , skb - > len , skb - > data , ( u32 ) buf_pa ,
( u32 ) ( ( u64 ) buf_pa > > 32 ) ) ;
card - > evt_buf_list [ i ] = skb ;
card - > evtbd_ring [ i ] = ( void * ) ( card - > evtbd_ring_vbase +
( sizeof ( * desc ) * i ) ) ;
desc = card - > evtbd_ring [ i ] ;
desc - > paddr = buf_pa ;
desc - > len = ( u16 ) skb - > len ;
desc - > flags = 0 ;
}
return 0 ;
}
/* This function cleans up TX buffer rings. If any of the buffer list has valid
* SKB address , associated SKB is freed .
*/
static void mwifiex_cleanup_txq_ring ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:09 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2013-02-08 18:18:07 -08:00
struct sk_buff * skb ;
struct mwifiex_pcie_buf_desc * desc ;
2013-02-08 18:18:09 -08:00
struct mwifiex_pfu_buf_desc * desc2 ;
2013-02-08 18:18:07 -08:00
int i ;
for ( i = 0 ; i < MWIFIEX_MAX_TXRX_BD ; i + + ) {
2013-02-08 18:18:09 -08:00
if ( reg - > pfu_enabled ) {
desc2 = card - > txbd_ring [ i ] ;
if ( card - > tx_buf_list [ i ] ) {
skb = card - > tx_buf_list [ i ] ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb ,
PCI_DMA_TODEVICE ) ;
2013-02-08 18:18:09 -08:00
dev_kfree_skb_any ( skb ) ;
}
memset ( desc2 , 0 , sizeof ( * desc2 ) ) ;
} else {
desc = card - > txbd_ring [ i ] ;
if ( card - > tx_buf_list [ i ] ) {
skb = card - > tx_buf_list [ i ] ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb ,
PCI_DMA_TODEVICE ) ;
2013-02-08 18:18:09 -08:00
dev_kfree_skb_any ( skb ) ;
}
memset ( desc , 0 , sizeof ( * desc ) ) ;
2013-02-08 18:18:07 -08:00
}
card - > tx_buf_list [ i ] = NULL ;
}
return ;
}
/* This function cleans up RX buffer rings. If any of the buffer list has valid
* SKB address , associated SKB is freed .
*/
static void mwifiex_cleanup_rxq_ring ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:09 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2013-02-08 18:18:07 -08:00
struct mwifiex_pcie_buf_desc * desc ;
2013-02-08 18:18:09 -08:00
struct mwifiex_pfu_buf_desc * desc2 ;
2013-02-08 18:18:07 -08:00
struct sk_buff * skb ;
int i ;
for ( i = 0 ; i < MWIFIEX_MAX_TXRX_BD ; i + + ) {
2013-02-08 18:18:09 -08:00
if ( reg - > pfu_enabled ) {
desc2 = card - > rxbd_ring [ i ] ;
if ( card - > rx_buf_list [ i ] ) {
skb = card - > rx_buf_list [ i ] ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb ,
PCI_DMA_FROMDEVICE ) ;
2013-02-08 18:18:09 -08:00
dev_kfree_skb_any ( skb ) ;
}
memset ( desc2 , 0 , sizeof ( * desc2 ) ) ;
} else {
desc = card - > rxbd_ring [ i ] ;
if ( card - > rx_buf_list [ i ] ) {
skb = card - > rx_buf_list [ i ] ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb ,
PCI_DMA_FROMDEVICE ) ;
2013-02-08 18:18:09 -08:00
dev_kfree_skb_any ( skb ) ;
}
memset ( desc , 0 , sizeof ( * desc ) ) ;
2013-02-08 18:18:07 -08:00
}
2013-02-08 18:18:09 -08:00
card - > rx_buf_list [ i ] = NULL ;
2013-02-08 18:18:07 -08:00
}
return ;
}
/* This function cleans up event buffer rings. If any of the buffer list has
* valid SKB address , associated SKB is freed .
*/
static void mwifiex_cleanup_evt_ring ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:08 -08:00
struct mwifiex_evt_buf_desc * desc ;
2013-02-08 18:18:07 -08:00
struct sk_buff * skb ;
int i ;
for ( i = 0 ; i < MWIFIEX_MAX_EVT_BD ; i + + ) {
desc = card - > evtbd_ring [ i ] ;
if ( card - > evt_buf_list [ i ] ) {
skb = card - > evt_buf_list [ i ] ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb ,
PCI_DMA_FROMDEVICE ) ;
2013-02-08 18:18:07 -08:00
dev_kfree_skb_any ( skb ) ;
}
card - > evt_buf_list [ i ] = NULL ;
memset ( desc , 0 , sizeof ( * desc ) ) ;
}
return ;
}
/* This function creates buffer descriptor ring for TX
2011-10-11 17:41:21 -07:00
*/
static int mwifiex_pcie_create_txbd_ring ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
/*
* driver maintaines the write pointer and firmware maintaines the read
* pointer . The write pointer starts at 0 ( zero ) while the read pointer
* starts at zero with rollover bit set
*/
card - > txbd_wrptr = 0 ;
2013-02-08 18:18:09 -08:00
if ( reg - > pfu_enabled )
card - > txbd_rdptr = 0 ;
else
card - > txbd_rdptr | = reg - > tx_rollover_ind ;
2011-10-11 17:41:21 -07:00
/* allocate shared memory for the BD ring and divide the same in to
several descriptors */
2013-02-08 18:18:09 -08:00
if ( reg - > pfu_enabled )
card - > txbd_ring_size = sizeof ( struct mwifiex_pfu_buf_desc ) *
MWIFIEX_MAX_TXRX_BD ;
else
card - > txbd_ring_size = sizeof ( struct mwifiex_pcie_buf_desc ) *
MWIFIEX_MAX_TXRX_BD ;
2011-10-11 17:41:21 -07:00
dev_dbg ( adapter - > dev , " info: txbd_ring: Allocating %d bytes \n " ,
2012-03-13 19:22:37 -07:00
card - > txbd_ring_size ) ;
2013-01-03 21:21:30 -08:00
card - > txbd_ring_vbase = pci_alloc_consistent ( card - > dev ,
card - > txbd_ring_size ,
& card - > txbd_ring_pbase ) ;
2011-10-11 17:41:21 -07:00
if ( ! card - > txbd_ring_vbase ) {
2013-01-03 21:21:30 -08:00
dev_err ( adapter - > dev ,
" allocate consistent memory (%d bytes) failed! \n " ,
card - > txbd_ring_size ) ;
2011-12-08 20:41:03 -08:00
return - ENOMEM ;
2011-10-11 17:41:21 -07:00
}
2012-03-13 19:22:37 -07:00
dev_dbg ( adapter - > dev ,
" info: txbd_ring - base: %p, pbase: %#x:%x, len: %x \n " ,
2013-01-03 21:21:30 -08:00
card - > txbd_ring_vbase , ( unsigned int ) card - > txbd_ring_pbase ,
2012-03-13 19:22:37 -07:00
( u32 ) ( ( u64 ) card - > txbd_ring_pbase > > 32 ) , card - > txbd_ring_size ) ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:07 -08:00
return mwifiex_init_txq_ring ( adapter ) ;
2011-10-11 17:41:21 -07:00
}
static int mwifiex_pcie_delete_txbd_ring ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:07 -08:00
mwifiex_cleanup_txq_ring ( adapter ) ;
2011-10-11 17:41:21 -07:00
2013-01-03 21:21:30 -08:00
if ( card - > txbd_ring_vbase )
pci_free_consistent ( card - > dev , card - > txbd_ring_size ,
card - > txbd_ring_vbase ,
card - > txbd_ring_pbase ) ;
2011-10-11 17:41:21 -07:00
card - > txbd_ring_size = 0 ;
card - > txbd_wrptr = 0 ;
2013-02-08 18:18:06 -08:00
card - > txbd_rdptr = 0 | reg - > tx_rollover_ind ;
2011-10-11 17:41:21 -07:00
card - > txbd_ring_vbase = NULL ;
2013-01-03 21:21:30 -08:00
card - > txbd_ring_pbase = 0 ;
2011-10-11 17:41:21 -07:00
return 0 ;
}
/*
* This function creates buffer descriptor ring for RX
*/
static int mwifiex_pcie_create_rxbd_ring ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
/*
* driver maintaines the read pointer and firmware maintaines the write
* pointer . The write pointer starts at 0 ( zero ) while the read pointer
* starts at zero with rollover bit set
*/
card - > rxbd_wrptr = 0 ;
2013-02-08 18:18:06 -08:00
card - > rxbd_rdptr = reg - > rx_rollover_ind ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:09 -08:00
if ( reg - > pfu_enabled )
card - > rxbd_ring_size = sizeof ( struct mwifiex_pfu_buf_desc ) *
MWIFIEX_MAX_TXRX_BD ;
else
card - > rxbd_ring_size = sizeof ( struct mwifiex_pcie_buf_desc ) *
MWIFIEX_MAX_TXRX_BD ;
2011-10-11 17:41:21 -07:00
dev_dbg ( adapter - > dev , " info: rxbd_ring: Allocating %d bytes \n " ,
2012-03-13 19:22:37 -07:00
card - > rxbd_ring_size ) ;
2013-01-03 21:21:30 -08:00
card - > rxbd_ring_vbase = pci_alloc_consistent ( card - > dev ,
card - > rxbd_ring_size ,
& card - > rxbd_ring_pbase ) ;
2011-10-11 17:41:21 -07:00
if ( ! card - > rxbd_ring_vbase ) {
2013-01-03 21:21:30 -08:00
dev_err ( adapter - > dev ,
" allocate consistent memory (%d bytes) failed! \n " ,
card - > rxbd_ring_size ) ;
2011-12-08 20:41:03 -08:00
return - ENOMEM ;
2011-10-11 17:41:21 -07:00
}
2012-03-13 19:22:37 -07:00
dev_dbg ( adapter - > dev ,
" info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x \n " ,
card - > rxbd_ring_vbase , ( u32 ) card - > rxbd_ring_pbase ,
( u32 ) ( ( u64 ) card - > rxbd_ring_pbase > > 32 ) ,
card - > rxbd_ring_size ) ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:07 -08:00
return mwifiex_init_rxq_ring ( adapter ) ;
2011-10-11 17:41:21 -07:00
}
/*
* This function deletes Buffer descriptor ring for RX
*/
static int mwifiex_pcie_delete_rxbd_ring ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:07 -08:00
mwifiex_cleanup_rxq_ring ( adapter ) ;
2011-10-11 17:41:21 -07:00
2013-01-03 21:21:30 -08:00
if ( card - > rxbd_ring_vbase )
pci_free_consistent ( card - > dev , card - > rxbd_ring_size ,
card - > rxbd_ring_vbase ,
card - > rxbd_ring_pbase ) ;
2011-10-11 17:41:21 -07:00
card - > rxbd_ring_size = 0 ;
card - > rxbd_wrptr = 0 ;
2013-02-08 18:18:06 -08:00
card - > rxbd_rdptr = 0 | reg - > rx_rollover_ind ;
2011-10-11 17:41:21 -07:00
card - > rxbd_ring_vbase = NULL ;
2013-01-03 21:21:30 -08:00
card - > rxbd_ring_pbase = 0 ;
2011-10-11 17:41:21 -07:00
return 0 ;
}
/*
* This function creates buffer descriptor ring for Events
*/
static int mwifiex_pcie_create_evtbd_ring ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
/*
* driver maintaines the read pointer and firmware maintaines the write
* pointer . The write pointer starts at 0 ( zero ) while the read pointer
* starts at zero with rollover bit set
*/
card - > evtbd_wrptr = 0 ;
2013-02-08 18:18:06 -08:00
card - > evtbd_rdptr = reg - > evt_rollover_ind ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:08 -08:00
card - > evtbd_ring_size = sizeof ( struct mwifiex_evt_buf_desc ) *
2013-02-08 18:18:09 -08:00
MWIFIEX_MAX_EVT_BD ;
2011-10-11 17:41:21 -07:00
dev_dbg ( adapter - > dev , " info: evtbd_ring: Allocating %d bytes \n " ,
2012-03-13 19:22:37 -07:00
card - > evtbd_ring_size ) ;
2013-01-03 21:21:30 -08:00
card - > evtbd_ring_vbase = pci_alloc_consistent ( card - > dev ,
card - > evtbd_ring_size ,
& card - > evtbd_ring_pbase ) ;
2011-10-11 17:41:21 -07:00
if ( ! card - > evtbd_ring_vbase ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
2013-01-03 21:21:30 -08:00
" allocate consistent memory (%d bytes) failed! \n " ,
card - > evtbd_ring_size ) ;
2011-12-08 20:41:03 -08:00
return - ENOMEM ;
2011-10-11 17:41:21 -07:00
}
2012-03-13 19:22:37 -07:00
dev_dbg ( adapter - > dev ,
" info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x \n " ,
card - > evtbd_ring_vbase , ( u32 ) card - > evtbd_ring_pbase ,
( u32 ) ( ( u64 ) card - > evtbd_ring_pbase > > 32 ) ,
card - > evtbd_ring_size ) ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:07 -08:00
return mwifiex_pcie_init_evt_ring ( adapter ) ;
2011-10-11 17:41:21 -07:00
}
/*
* This function deletes Buffer descriptor ring for Events
*/
static int mwifiex_pcie_delete_evtbd_ring ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:07 -08:00
mwifiex_cleanup_evt_ring ( adapter ) ;
2011-10-11 17:41:21 -07:00
2013-01-03 21:21:30 -08:00
if ( card - > evtbd_ring_vbase )
pci_free_consistent ( card - > dev , card - > evtbd_ring_size ,
card - > evtbd_ring_vbase ,
card - > evtbd_ring_pbase ) ;
2011-10-11 17:41:21 -07:00
card - > evtbd_wrptr = 0 ;
2013-02-08 18:18:06 -08:00
card - > evtbd_rdptr = 0 | reg - > evt_rollover_ind ;
2011-10-11 17:41:21 -07:00
card - > evtbd_ring_size = 0 ;
card - > evtbd_ring_vbase = NULL ;
2013-01-03 21:21:30 -08:00
card - > evtbd_ring_pbase = 0 ;
2011-10-11 17:41:21 -07:00
return 0 ;
}
/*
* This function allocates a buffer for CMDRSP
*/
static int mwifiex_pcie_alloc_cmdrsp_buf ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
struct sk_buff * skb ;
/* Allocate memory for receiving command response data */
skb = dev_alloc_skb ( MWIFIEX_UPLD_SIZE ) ;
if ( ! skb ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" Unable to allocate skb for command response data. \n " ) ;
2011-10-11 17:41:21 -07:00
return - ENOMEM ;
}
skb_put ( skb , MWIFIEX_UPLD_SIZE ) ;
2013-01-03 21:21:30 -08:00
if ( mwifiex_map_pci_memory ( adapter , skb , MWIFIEX_UPLD_SIZE ,
PCI_DMA_FROMDEVICE ) )
return - 1 ;
2011-10-11 17:41:21 -07:00
2013-01-03 21:21:30 -08:00
card - > cmdrsp_buf = skb ;
2011-10-11 17:41:21 -07:00
return 0 ;
}
/*
* This function deletes a buffer for CMDRSP
*/
static int mwifiex_pcie_delete_cmdrsp_buf ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card ;
if ( ! adapter )
return 0 ;
card = adapter - > card ;
2013-01-03 21:21:30 -08:00
if ( card & & card - > cmdrsp_buf ) {
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , card - > cmdrsp_buf ,
PCI_DMA_FROMDEVICE ) ;
2011-10-11 17:41:21 -07:00
dev_kfree_skb_any ( card - > cmdrsp_buf ) ;
2013-01-03 21:21:30 -08:00
}
2011-10-11 17:41:21 -07:00
2013-01-03 21:21:30 -08:00
if ( card & & card - > cmd_buf ) {
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , card - > cmd_buf ,
PCI_DMA_TODEVICE ) ;
2013-01-03 21:21:30 -08:00
}
2011-10-11 17:41:21 -07:00
return 0 ;
}
/*
* This function allocates a buffer for sleep cookie
*/
static int mwifiex_pcie_alloc_sleep_cookie_buf ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-01-03 21:21:30 -08:00
card - > sleep_cookie_vbase = pci_alloc_consistent ( card - > dev , sizeof ( u32 ) ,
& card - > sleep_cookie_pbase ) ;
if ( ! card - > sleep_cookie_vbase ) {
dev_err ( adapter - > dev , " pci_alloc_consistent failed! \n " ) ;
2011-10-11 17:41:21 -07:00
return - ENOMEM ;
}
/* Init val of Sleep Cookie */
2013-01-03 21:21:30 -08:00
* ( u32 * ) card - > sleep_cookie_vbase = FW_AWAKE_COOKIE ;
2011-10-11 17:41:21 -07:00
dev_dbg ( adapter - > dev , " alloc_scook: sleep cookie=0x%x \n " ,
2013-01-03 21:21:30 -08:00
* ( ( u32 * ) card - > sleep_cookie_vbase ) ) ;
2011-10-11 17:41:21 -07:00
return 0 ;
}
/*
* This function deletes buffer for sleep cookie
*/
static int mwifiex_pcie_delete_sleep_cookie_buf ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card ;
if ( ! adapter )
return 0 ;
card = adapter - > card ;
2013-01-03 21:21:30 -08:00
if ( card & & card - > sleep_cookie_vbase ) {
pci_free_consistent ( card - > dev , sizeof ( u32 ) ,
card - > sleep_cookie_vbase ,
card - > sleep_cookie_pbase ) ;
card - > sleep_cookie_vbase = NULL ;
2011-10-11 17:41:21 -07:00
}
return 0 ;
}
2013-01-03 21:21:31 -08:00
/* This function flushes the TX buffer descriptor ring
* This function defined as handler is also called while cleaning TXRX
* during disconnect / bss stop .
*/
static int mwifiex_clean_pcie_ring_buf ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-20 21:12:58 -08:00
if ( ! mwifiex_pcie_txbd_empty ( card , card - > txbd_rdptr ) ) {
2013-01-03 21:21:31 -08:00
card - > txbd_flush = 1 ;
/* write pointer already set at last send
* send dnld - rdy intr again , wait for completion .
*/
if ( mwifiex_write_reg ( adapter , PCIE_CPU_INT_EVENT ,
CPU_INTR_DNLD_RDY ) ) {
dev_err ( adapter - > dev ,
" failed to assert dnld-rdy interrupt. \n " ) ;
return - 1 ;
}
}
return 0 ;
}
2011-10-11 17:41:21 -07:00
/*
2013-01-03 21:21:32 -08:00
* This function unmaps and frees downloaded data buffer
2011-10-11 17:41:21 -07:00
*/
2013-01-03 21:21:32 -08:00
static int mwifiex_pcie_send_data_complete ( struct mwifiex_adapter * adapter )
2011-10-11 17:41:21 -07:00
{
2013-01-03 21:21:32 -08:00
struct sk_buff * skb ;
2013-02-08 18:18:09 -08:00
u32 wrdoneidx , rdptr , num_tx_buffs , unmap_count = 0 ;
2013-02-08 18:18:08 -08:00
struct mwifiex_pcie_buf_desc * desc ;
2013-02-08 18:18:09 -08:00
struct mwifiex_pfu_buf_desc * desc2 ;
2011-10-11 17:41:21 -07:00
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
if ( ! mwifiex_pcie_ok_to_access_hw ( adapter ) )
mwifiex_pm_wakeup_card ( adapter ) ;
/* Read the TX ring read pointer set by firmware */
2013-02-08 18:18:06 -08:00
if ( mwifiex_read_reg ( adapter , reg - > tx_rdptr , & rdptr ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
2013-02-08 18:18:06 -08:00
" SEND COMP: failed to read reg->tx_rdptr \n " ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
2013-01-03 21:21:32 -08:00
dev_dbg ( adapter - > dev , " SEND COMP: rdptr_prev=0x%x, rdptr=0x%x \n " ,
card - > txbd_rdptr , rdptr ) ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:09 -08:00
num_tx_buffs = MWIFIEX_MAX_TXRX_BD < < reg - > tx_start_ptr ;
2013-01-03 21:21:32 -08:00
/* free from previous txbd_rdptr to current txbd_rdptr */
2013-02-08 18:18:06 -08:00
while ( ( ( card - > txbd_rdptr & reg - > tx_mask ) ! =
( rdptr & reg - > tx_mask ) ) | |
( ( card - > txbd_rdptr & reg - > tx_rollover_ind ) ! =
( rdptr & reg - > tx_rollover_ind ) ) ) {
2013-02-08 18:18:09 -08:00
wrdoneidx = ( card - > txbd_rdptr & reg - > tx_mask ) > >
reg - > tx_start_ptr ;
2013-01-03 21:21:32 -08:00
skb = card - > tx_buf_list [ wrdoneidx ] ;
2014-02-07 16:25:50 -08:00
2013-01-03 21:21:32 -08:00
if ( skb ) {
dev_dbg ( adapter - > dev ,
" SEND COMP: Detach skb %p at txbd_rdidx=%d \n " ,
skb , wrdoneidx ) ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb ,
PCI_DMA_TODEVICE ) ;
2013-01-03 21:21:32 -08:00
unmap_count + + ;
if ( card - > txbd_flush )
mwifiex_write_data_complete ( adapter , skb , 0 ,
- 1 ) ;
else
mwifiex_write_data_complete ( adapter , skb , 0 , 0 ) ;
}
card - > tx_buf_list [ wrdoneidx ] = NULL ;
2013-02-08 18:18:09 -08:00
if ( reg - > pfu_enabled ) {
2014-03-24 13:15:39 -07:00
desc2 = card - > txbd_ring [ wrdoneidx ] ;
2013-02-08 18:18:09 -08:00
memset ( desc2 , 0 , sizeof ( * desc2 ) ) ;
} else {
desc = card - > txbd_ring [ wrdoneidx ] ;
memset ( desc , 0 , sizeof ( * desc ) ) ;
}
switch ( card - > dev - > device ) {
case PCIE_DEVICE_ID_MARVELL_88W8766P :
card - > txbd_rdptr + + ;
break ;
case PCIE_DEVICE_ID_MARVELL_88W8897 :
card - > txbd_rdptr + = reg - > ring_tx_start_ptr ;
break ;
}
2013-01-03 21:21:32 -08:00
2013-02-08 18:18:06 -08:00
if ( ( card - > txbd_rdptr & reg - > tx_mask ) = = num_tx_buffs )
2013-01-03 21:21:32 -08:00
card - > txbd_rdptr = ( ( card - > txbd_rdptr &
2013-02-08 18:18:06 -08:00
reg - > tx_rollover_ind ) ^
reg - > tx_rollover_ind ) ;
2013-01-03 21:21:32 -08:00
}
if ( unmap_count )
adapter - > data_sent = false ;
if ( card - > txbd_flush ) {
2013-02-15 21:37:54 -08:00
if ( mwifiex_pcie_txbd_empty ( card , card - > txbd_rdptr ) )
2013-01-03 21:21:32 -08:00
card - > txbd_flush = 0 ;
else
mwifiex_clean_pcie_ring_buf ( adapter ) ;
}
return 0 ;
}
/* This function sends data buffer to device. First 4 bytes of payload
* are filled with payload length and payload type . Then this payload
* is mapped to PCI device memory . Tx ring pointers are advanced accordingly .
* Download ready interrupt to FW is deffered if Tx ring is not full and
* additional payload can be accomodated .
2014-05-13 19:50:13 -07:00
* Caller must ensure tx_param parameter to this function is not NULL .
2013-01-03 21:21:32 -08:00
*/
static int
mwifiex_pcie_send_data ( struct mwifiex_adapter * adapter , struct sk_buff * skb ,
struct mwifiex_tx_param * tx_param )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2013-02-08 18:18:09 -08:00
u32 wrindx , num_tx_buffs , rx_val ;
2013-01-03 21:21:32 -08:00
int ret ;
dma_addr_t buf_pa ;
2013-03-04 16:27:55 -08:00
struct mwifiex_pcie_buf_desc * desc = NULL ;
struct mwifiex_pfu_buf_desc * desc2 = NULL ;
2013-01-03 21:21:32 -08:00
__le16 * tmp ;
if ( ! ( skb - > data & & skb - > len ) ) {
dev_err ( adapter - > dev , " %s(): invalid parameter <%p, %#x> \n " ,
__func__ , skb - > data , skb - > len ) ;
return - 1 ;
}
if ( ! mwifiex_pcie_ok_to_access_hw ( adapter ) )
mwifiex_pm_wakeup_card ( adapter ) ;
2013-02-08 18:18:09 -08:00
num_tx_buffs = MWIFIEX_MAX_TXRX_BD < < reg - > tx_start_ptr ;
2013-01-03 21:21:32 -08:00
dev_dbg ( adapter - > dev , " info: SEND DATA: <Rd: %#x, Wr: %#x> \n " ,
card - > txbd_rdptr , card - > txbd_wrptr ) ;
if ( mwifiex_pcie_txbd_not_full ( card ) ) {
2011-10-11 17:41:21 -07:00
u8 * payload ;
adapter - > data_sent = true ;
2013-01-03 21:21:32 -08:00
payload = skb - > data ;
2011-10-11 17:41:21 -07:00
tmp = ( __le16 * ) & payload [ 0 ] ;
* tmp = cpu_to_le16 ( ( u16 ) skb - > len ) ;
tmp = ( __le16 * ) & payload [ 2 ] ;
* tmp = cpu_to_le16 ( MWIFIEX_TYPE_DATA ) ;
2013-01-03 21:21:32 -08:00
2014-02-07 16:25:50 -08:00
if ( mwifiex_map_pci_memory ( adapter , skb , skb - > len ,
2013-01-03 21:21:32 -08:00
PCI_DMA_TODEVICE ) )
return - 1 ;
2013-02-08 18:18:09 -08:00
wrindx = ( card - > txbd_wrptr & reg - > tx_mask ) > > reg - > tx_start_ptr ;
2014-02-07 16:25:50 -08:00
buf_pa = MWIFIEX_SKB_DMA_ADDR ( skb ) ;
2013-01-03 21:21:32 -08:00
card - > tx_buf_list [ wrindx ] = skb ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:09 -08:00
if ( reg - > pfu_enabled ) {
2014-03-24 13:15:39 -07:00
desc2 = card - > txbd_ring [ wrindx ] ;
2013-02-08 18:18:09 -08:00
desc2 - > paddr = buf_pa ;
desc2 - > len = ( u16 ) skb - > len ;
desc2 - > frag_len = ( u16 ) skb - > len ;
desc2 - > offset = 0 ;
desc2 - > flags = MWIFIEX_BD_FLAG_FIRST_DESC |
MWIFIEX_BD_FLAG_LAST_DESC ;
} else {
desc = card - > txbd_ring [ wrindx ] ;
desc - > paddr = buf_pa ;
desc - > len = ( u16 ) skb - > len ;
desc - > flags = MWIFIEX_BD_FLAG_FIRST_DESC |
MWIFIEX_BD_FLAG_LAST_DESC ;
}
switch ( card - > dev - > device ) {
case PCIE_DEVICE_ID_MARVELL_88W8766P :
card - > txbd_wrptr + + ;
break ;
case PCIE_DEVICE_ID_MARVELL_88W8897 :
card - > txbd_wrptr + = reg - > ring_tx_start_ptr ;
break ;
}
if ( ( card - > txbd_wrptr & reg - > tx_mask ) = = num_tx_buffs )
2011-10-11 17:41:21 -07:00
card - > txbd_wrptr = ( ( card - > txbd_wrptr &
2013-02-08 18:18:06 -08:00
reg - > tx_rollover_ind ) ^
reg - > tx_rollover_ind ) ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:09 -08:00
rx_val = card - > rxbd_rdptr & reg - > rx_wrap_mask ;
2013-02-08 18:18:06 -08:00
/* Write the TX ring write pointer in to reg->tx_wrptr */
if ( mwifiex_write_reg ( adapter , reg - > tx_wrptr ,
2013-02-08 18:18:09 -08:00
card - > txbd_wrptr | rx_val ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
2013-02-08 18:18:06 -08:00
" SEND DATA: failed to write reg->tx_wrptr \n " ) ;
2013-01-03 21:21:32 -08:00
ret = - 1 ;
goto done_unmap ;
2011-10-11 17:41:21 -07:00
}
2013-01-03 21:21:32 -08:00
if ( ( mwifiex_pcie_txbd_not_full ( card ) ) & &
tx_param - > next_pkt_len ) {
/* have more packets and TxBD still can hold more */
dev_dbg ( adapter - > dev ,
" SEND DATA: delay dnld-rdy interrupt. \n " ) ;
adapter - > data_sent = false ;
} else {
/* Send the TX ready interrupt */
if ( mwifiex_write_reg ( adapter , PCIE_CPU_INT_EVENT ,
CPU_INTR_DNLD_RDY ) ) {
dev_err ( adapter - > dev ,
" SEND DATA: failed to assert dnld-rdy interrupt. \n " ) ;
ret = - 1 ;
goto done_unmap ;
}
2011-10-11 17:41:21 -07:00
}
dev_dbg ( adapter - > dev , " info: SEND DATA: Updated <Rd: %#x, Wr: "
2012-03-13 19:22:37 -07:00
" %#x> and sent packet to firmware successfully \n " ,
2013-01-03 21:21:32 -08:00
card - > txbd_rdptr , card - > txbd_wrptr ) ;
2011-10-11 17:41:21 -07:00
} else {
2012-03-13 19:22:37 -07:00
dev_dbg ( adapter - > dev ,
" info: TX Ring full, can't send packets to fw \n " ) ;
2011-10-11 17:41:21 -07:00
adapter - > data_sent = true ;
/* Send the TX ready interrupt */
if ( mwifiex_write_reg ( adapter , PCIE_CPU_INT_EVENT ,
CPU_INTR_DNLD_RDY ) )
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" SEND DATA: failed to assert door-bell intr \n " ) ;
2011-10-11 17:41:21 -07:00
return - EBUSY ;
}
2013-01-03 21:21:32 -08:00
return - EINPROGRESS ;
done_unmap :
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb , PCI_DMA_TODEVICE ) ;
2013-01-03 21:21:32 -08:00
card - > tx_buf_list [ wrindx ] = NULL ;
2013-02-08 18:18:09 -08:00
if ( reg - > pfu_enabled )
memset ( desc2 , 0 , sizeof ( * desc2 ) ) ;
else
memset ( desc , 0 , sizeof ( * desc ) ) ;
2013-01-03 21:21:32 -08:00
return ret ;
2011-10-11 17:41:21 -07:00
}
/*
* This function handles received buffer ring and
* dispatches packets to upper
*/
static int mwifiex_pcie_process_recv_data ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2013-02-08 18:18:09 -08:00
u32 wrptr , rd_index , tx_val ;
2013-01-03 21:21:32 -08:00
dma_addr_t buf_pa ;
2011-10-11 17:41:21 -07:00
int ret = 0 ;
struct sk_buff * skb_tmp = NULL ;
2013-02-08 18:18:08 -08:00
struct mwifiex_pcie_buf_desc * desc ;
2013-02-08 18:18:09 -08:00
struct mwifiex_pfu_buf_desc * desc2 ;
2011-10-11 17:41:21 -07:00
2013-01-03 21:21:32 -08:00
if ( ! mwifiex_pcie_ok_to_access_hw ( adapter ) )
mwifiex_pm_wakeup_card ( adapter ) ;
2011-10-11 17:41:21 -07:00
/* Read the RX ring Write pointer set by firmware */
2013-02-08 18:18:06 -08:00
if ( mwifiex_read_reg ( adapter , reg - > rx_wrptr , & wrptr ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
2013-02-08 18:18:06 -08:00
" RECV DATA: failed to read reg->rx_wrptr \n " ) ;
2011-10-11 17:41:21 -07:00
ret = - 1 ;
goto done ;
}
2013-01-03 21:21:32 -08:00
card - > rxbd_wrptr = wrptr ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:06 -08:00
while ( ( ( wrptr & reg - > rx_mask ) ! =
( card - > rxbd_rdptr & reg - > rx_mask ) ) | |
( ( wrptr & reg - > rx_rollover_ind ) = =
( card - > rxbd_rdptr & reg - > rx_rollover_ind ) ) ) {
2011-10-11 17:41:21 -07:00
struct sk_buff * skb_data ;
u16 rx_len ;
2013-01-03 21:21:32 -08:00
__le16 pkt_len ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:06 -08:00
rd_index = card - > rxbd_rdptr & reg - > rx_mask ;
2011-10-11 17:41:21 -07:00
skb_data = card - > rx_buf_list [ rd_index ] ;
2014-02-18 15:41:55 -08:00
/* If skb allocation was failed earlier for Rx packet,
* rx_buf_list [ rd_index ] would have been left with a NULL .
*/
if ( ! skb_data )
return - ENOMEM ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb_data , PCI_DMA_FROMDEVICE ) ;
2013-01-03 21:21:32 -08:00
card - > rx_buf_list [ rd_index ] = NULL ;
2011-10-11 17:41:21 -07:00
/* Get data length from interface header -
2013-01-03 21:21:32 -08:00
* first 2 bytes for len , next 2 bytes is for type
*/
pkt_len = * ( ( __le16 * ) skb_data - > data ) ;
rx_len = le16_to_cpu ( pkt_len ) ;
2014-09-12 20:08:47 +05:30
if ( WARN_ON ( rx_len < = INTF_HEADER_LEN | |
rx_len > MWIFIEX_RX_DATA_BUF_SIZE ) ) {
dev_err ( adapter - > dev ,
" Invalid RX len %d, Rd=%#x, Wr=%#x \n " ,
rx_len , card - > rxbd_rdptr , wrptr ) ;
dev_kfree_skb_any ( skb_data ) ;
} else {
skb_put ( skb_data , rx_len ) ;
dev_dbg ( adapter - > dev ,
" info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d \n " ,
card - > rxbd_rdptr , wrptr , rx_len ) ;
skb_pull ( skb_data , INTF_HEADER_LEN ) ;
2014-09-12 20:08:59 +05:30
if ( adapter - > rx_work_enabled ) {
skb_queue_tail ( & adapter - > rx_data_q , skb_data ) ;
adapter - > data_received = true ;
atomic_inc ( & adapter - > rx_pending ) ;
} else {
mwifiex_handle_rx_packet ( adapter , skb_data ) ;
}
2014-09-12 20:08:47 +05:30
}
2013-01-03 21:21:32 -08:00
skb_tmp = dev_alloc_skb ( MWIFIEX_RX_DATA_BUF_SIZE ) ;
2011-10-11 17:41:21 -07:00
if ( ! skb_tmp ) {
2013-01-03 21:21:32 -08:00
dev_err ( adapter - > dev ,
" Unable to allocate skb. \n " ) ;
return - ENOMEM ;
2011-10-11 17:41:21 -07:00
}
2013-01-03 21:21:32 -08:00
if ( mwifiex_map_pci_memory ( adapter , skb_tmp ,
MWIFIEX_RX_DATA_BUF_SIZE ,
PCI_DMA_FROMDEVICE ) )
return - 1 ;
2014-02-07 16:25:50 -08:00
buf_pa = MWIFIEX_SKB_DMA_ADDR ( skb_tmp ) ;
2013-01-03 21:21:32 -08:00
dev_dbg ( adapter - > dev ,
" RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d \n " ,
skb_tmp , rd_index ) ;
card - > rx_buf_list [ rd_index ] = skb_tmp ;
2013-02-08 18:18:09 -08:00
if ( reg - > pfu_enabled ) {
2014-03-24 13:15:39 -07:00
desc2 = card - > rxbd_ring [ rd_index ] ;
2013-02-08 18:18:09 -08:00
desc2 - > paddr = buf_pa ;
desc2 - > len = skb_tmp - > len ;
desc2 - > frag_len = skb_tmp - > len ;
desc2 - > offset = 0 ;
desc2 - > flags = reg - > ring_flag_sop | reg - > ring_flag_eop ;
} else {
desc = card - > rxbd_ring [ rd_index ] ;
desc - > paddr = buf_pa ;
desc - > len = skb_tmp - > len ;
desc - > flags = 0 ;
}
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:06 -08:00
if ( ( + + card - > rxbd_rdptr & reg - > rx_mask ) = =
2011-10-11 17:41:21 -07:00
MWIFIEX_MAX_TXRX_BD ) {
card - > rxbd_rdptr = ( ( card - > rxbd_rdptr &
2013-02-08 18:18:06 -08:00
reg - > rx_rollover_ind ) ^
reg - > rx_rollover_ind ) ;
2011-10-11 17:41:21 -07:00
}
dev_dbg ( adapter - > dev , " info: RECV DATA: <Rd: %#x, Wr: %#x> \n " ,
2012-03-13 19:22:37 -07:00
card - > rxbd_rdptr , wrptr ) ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:09 -08:00
tx_val = card - > txbd_wrptr & reg - > tx_wrap_mask ;
2013-02-08 18:18:06 -08:00
/* Write the RX ring read pointer in to reg->rx_rdptr */
if ( mwifiex_write_reg ( adapter , reg - > rx_rdptr ,
2013-02-08 18:18:09 -08:00
card - > rxbd_rdptr | tx_val ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
2013-02-08 18:18:06 -08:00
" RECV DATA: failed to write reg->rx_rdptr \n " ) ;
2011-10-11 17:41:21 -07:00
ret = - 1 ;
goto done ;
}
/* Read the RX ring Write pointer set by firmware */
2013-02-08 18:18:06 -08:00
if ( mwifiex_read_reg ( adapter , reg - > rx_wrptr , & wrptr ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
2013-02-08 18:18:06 -08:00
" RECV DATA: failed to read reg->rx_wrptr \n " ) ;
2011-10-11 17:41:21 -07:00
ret = - 1 ;
goto done ;
}
2012-03-13 19:22:37 -07:00
dev_dbg ( adapter - > dev ,
" info: RECV DATA: Rcvd packet from fw successfully \n " ) ;
2013-01-03 21:21:32 -08:00
card - > rxbd_wrptr = wrptr ;
2011-10-11 17:41:21 -07:00
}
done :
return ret ;
}
/*
* This function downloads the boot command to device
*/
static int
mwifiex_pcie_send_boot_cmd ( struct mwifiex_adapter * adapter , struct sk_buff * skb )
{
2013-01-03 21:21:30 -08:00
dma_addr_t buf_pa ;
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
2013-01-03 21:21:30 -08:00
if ( ! ( skb - > data & & skb - > len ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
2013-01-03 21:21:30 -08:00
" Invalid parameter in %s <%p. len %d> \n " ,
__func__ , skb - > data , skb - > len ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
2013-01-03 21:21:30 -08:00
if ( mwifiex_map_pci_memory ( adapter , skb , skb - > len , PCI_DMA_TODEVICE ) )
return - 1 ;
2014-02-07 16:25:50 -08:00
buf_pa = MWIFIEX_SKB_DMA_ADDR ( skb ) ;
2013-01-03 21:21:30 -08:00
2013-02-08 18:18:06 -08:00
/* Write the lower 32bits of the physical address to low command
* address scratch register
*/
if ( mwifiex_write_reg ( adapter , reg - > cmd_addr_lo , ( u32 ) buf_pa ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" %s: failed to write download command to boot code. \n " ,
__func__ ) ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb , PCI_DMA_TODEVICE ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
2013-02-08 18:18:06 -08:00
/* Write the upper 32bits of the physical address to high command
* address scratch register
*/
if ( mwifiex_write_reg ( adapter , reg - > cmd_addr_hi ,
2013-01-03 21:21:30 -08:00
( u32 ) ( ( u64 ) buf_pa > > 32 ) ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" %s: failed to write download command to boot code. \n " ,
__func__ ) ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb , PCI_DMA_TODEVICE ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
2013-02-08 18:18:06 -08:00
/* Write the command length to cmd_size scratch register */
if ( mwifiex_write_reg ( adapter , reg - > cmd_size , skb - > len ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
2013-02-08 18:18:06 -08:00
" %s: failed to write command len to cmd_size scratch reg \n " ,
2012-03-13 19:22:37 -07:00
__func__ ) ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb , PCI_DMA_TODEVICE ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
/* Ring the door bell */
if ( mwifiex_write_reg ( adapter , PCIE_CPU_INT_EVENT ,
CPU_INTR_DOOR_BELL ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" %s: failed to assert door-bell intr \n " , __func__ ) ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb , PCI_DMA_TODEVICE ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
return 0 ;
}
2013-01-03 21:21:29 -08:00
/* This function init rx port in firmware which in turn enables to receive data
* from device before transmitting any packet .
*/
static int mwifiex_pcie_init_fw_port ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2013-02-08 18:18:09 -08:00
int tx_wrap = card - > txbd_wrptr & reg - > tx_wrap_mask ;
2013-01-03 21:21:29 -08:00
2013-02-08 18:18:06 -08:00
/* Write the RX ring read pointer in to reg->rx_rdptr */
2013-02-08 18:18:09 -08:00
if ( mwifiex_write_reg ( adapter , reg - > rx_rdptr , card - > rxbd_rdptr |
tx_wrap ) ) {
2013-01-03 21:21:29 -08:00
dev_err ( adapter - > dev ,
2013-02-08 18:18:06 -08:00
" RECV DATA: failed to write reg->rx_rdptr \n " ) ;
2013-01-03 21:21:29 -08:00
return - 1 ;
}
return 0 ;
}
/* This function downloads commands to the device
2011-10-11 17:41:21 -07:00
*/
static int
mwifiex_pcie_send_cmd ( struct mwifiex_adapter * adapter , struct sk_buff * skb )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
int ret = 0 ;
2013-01-03 21:21:30 -08:00
dma_addr_t cmd_buf_pa , cmdrsp_buf_pa ;
u8 * payload = ( u8 * ) skb - > data ;
2011-10-11 17:41:21 -07:00
if ( ! ( skb - > data & & skb - > len ) ) {
dev_err ( adapter - > dev , " Invalid parameter in %s <%p, %#x> \n " ,
2012-03-13 19:22:37 -07:00
__func__ , skb - > data , skb - > len ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
/* Make sure a command response buffer is available */
if ( ! card - > cmdrsp_buf ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" No response buffer available, send command failed \n " ) ;
2011-10-11 17:41:21 -07:00
return - EBUSY ;
}
2013-01-03 21:21:30 -08:00
if ( ! mwifiex_pcie_ok_to_access_hw ( adapter ) )
mwifiex_pm_wakeup_card ( adapter ) ;
2011-10-11 17:41:21 -07:00
adapter - > cmd_sent = true ;
2013-01-03 21:21:30 -08:00
* ( __le16 * ) & payload [ 0 ] = cpu_to_le16 ( ( u16 ) skb - > len ) ;
* ( __le16 * ) & payload [ 2 ] = cpu_to_le16 ( MWIFIEX_TYPE_CMD ) ;
if ( mwifiex_map_pci_memory ( adapter , skb , skb - > len , PCI_DMA_TODEVICE ) )
return - 1 ;
card - > cmd_buf = skb ;
2011-10-11 17:41:21 -07:00
/* To send a command, the driver will:
1. Write the 64 bit physical address of the data buffer to
2013-02-08 18:18:06 -08:00
cmd response address low + cmd response address high
2011-10-11 17:41:21 -07:00
2. Ring the door bell ( i . e . set the door bell interrupt )
In response to door bell interrupt , the firmware will perform
the DMA of the command packet ( first header to obtain the total
length and then rest of the command ) .
*/
if ( card - > cmdrsp_buf ) {
2014-02-07 16:25:50 -08:00
cmdrsp_buf_pa = MWIFIEX_SKB_DMA_ADDR ( card - > cmdrsp_buf ) ;
2011-10-11 17:41:21 -07:00
/* Write the lower 32bits of the cmdrsp buffer physical
address */
2013-02-08 18:18:06 -08:00
if ( mwifiex_write_reg ( adapter , reg - > cmdrsp_addr_lo ,
2013-01-03 21:21:30 -08:00
( u32 ) cmdrsp_buf_pa ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" Failed to write download cmd to boot code. \n " ) ;
2011-10-11 17:41:21 -07:00
ret = - 1 ;
goto done ;
}
/* Write the upper 32bits of the cmdrsp buffer physical
address */
2013-02-08 18:18:06 -08:00
if ( mwifiex_write_reg ( adapter , reg - > cmdrsp_addr_hi ,
2013-01-03 21:21:30 -08:00
( u32 ) ( ( u64 ) cmdrsp_buf_pa > > 32 ) ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" Failed to write download cmd to boot code. \n " ) ;
2011-10-11 17:41:21 -07:00
ret = - 1 ;
goto done ;
}
}
2014-02-07 16:25:50 -08:00
cmd_buf_pa = MWIFIEX_SKB_DMA_ADDR ( card - > cmd_buf ) ;
2013-02-08 18:18:06 -08:00
/* Write the lower 32bits of the physical address to reg->cmd_addr_lo */
if ( mwifiex_write_reg ( adapter , reg - > cmd_addr_lo ,
( u32 ) cmd_buf_pa ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" Failed to write download cmd to boot code. \n " ) ;
2011-10-11 17:41:21 -07:00
ret = - 1 ;
goto done ;
}
2013-02-08 18:18:06 -08:00
/* Write the upper 32bits of the physical address to reg->cmd_addr_hi */
if ( mwifiex_write_reg ( adapter , reg - > cmd_addr_hi ,
2013-01-03 21:21:30 -08:00
( u32 ) ( ( u64 ) cmd_buf_pa > > 32 ) ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" Failed to write download cmd to boot code. \n " ) ;
2011-10-11 17:41:21 -07:00
ret = - 1 ;
goto done ;
}
2013-02-08 18:18:06 -08:00
/* Write the command length to reg->cmd_size */
if ( mwifiex_write_reg ( adapter , reg - > cmd_size ,
card - > cmd_buf - > len ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
2013-02-08 18:18:06 -08:00
" Failed to write cmd len to reg->cmd_size \n " ) ;
2011-10-11 17:41:21 -07:00
ret = - 1 ;
goto done ;
}
/* Ring the door bell */
if ( mwifiex_write_reg ( adapter , PCIE_CPU_INT_EVENT ,
CPU_INTR_DOOR_BELL ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" Failed to assert door-bell intr \n " ) ;
2011-10-11 17:41:21 -07:00
ret = - 1 ;
goto done ;
}
done :
if ( ret )
adapter - > cmd_sent = false ;
return 0 ;
}
/*
* This function handles command complete interrupt
*/
static int mwifiex_pcie_process_cmd_complete ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2012-03-13 19:22:37 -07:00
struct sk_buff * skb = card - > cmdrsp_buf ;
2011-10-11 17:41:21 -07:00
int count = 0 ;
2013-01-03 21:21:30 -08:00
u16 rx_len ;
__le16 pkt_len ;
2011-10-11 17:41:21 -07:00
dev_dbg ( adapter - > dev , " info: Rx CMD Response \n " ) ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb , PCI_DMA_FROMDEVICE ) ;
2013-01-03 21:21:30 -08:00
2014-02-07 16:25:51 -08:00
/* Unmap the command as a response has been received. */
if ( card - > cmd_buf ) {
mwifiex_unmap_pci_memory ( adapter , card - > cmd_buf ,
PCI_DMA_TODEVICE ) ;
card - > cmd_buf = NULL ;
}
2013-01-03 21:21:30 -08:00
pkt_len = * ( ( __le16 * ) skb - > data ) ;
rx_len = le16_to_cpu ( pkt_len ) ;
skb_trim ( skb , rx_len ) ;
skb_pull ( skb , INTF_HEADER_LEN ) ;
2011-10-11 17:41:21 -07:00
if ( ! adapter - > curr_cmd ) {
if ( adapter - > ps_state = = PS_STATE_SLEEP_CFM ) {
2012-03-13 19:22:37 -07:00
mwifiex_process_sleep_confirm_resp ( adapter , skb - > data ,
skb - > len ) ;
2014-02-18 15:41:56 -08:00
mwifiex_pcie_enable_host_int ( adapter ) ;
if ( mwifiex_write_reg ( adapter ,
PCIE_CPU_INT_EVENT ,
CPU_INTR_SLEEP_CFM_DONE ) ) {
dev_warn ( adapter - > dev ,
" Write register failed \n " ) ;
return - 1 ;
}
2014-03-18 22:19:17 -07:00
mwifiex_delay_for_sleep_cookie ( adapter ,
MWIFIEX_MAX_DELAY_COUNT ) ;
2013-02-12 14:38:32 -08:00
while ( reg - > sleep_cookie & & ( count + + < 10 ) & &
mwifiex_pcie_ok_to_access_hw ( adapter ) )
2012-03-12 19:35:11 -07:00
usleep_range ( 50 , 60 ) ;
2011-10-11 17:41:21 -07:00
} else {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" There is no command but got cmdrsp \n " ) ;
2011-10-11 17:41:21 -07:00
}
2012-03-13 19:22:37 -07:00
memcpy ( adapter - > upld_buf , skb - > data ,
min_t ( u32 , MWIFIEX_SIZE_OF_CMD_BUFFER , skb - > len ) ) ;
2013-03-20 17:56:23 -07:00
skb_push ( skb , INTF_HEADER_LEN ) ;
2013-01-03 21:21:30 -08:00
if ( mwifiex_map_pci_memory ( adapter , skb , MWIFIEX_UPLD_SIZE ,
PCI_DMA_FROMDEVICE ) )
return - 1 ;
2011-10-11 17:41:21 -07:00
} else if ( mwifiex_pcie_ok_to_access_hw ( adapter ) ) {
2012-03-13 19:22:37 -07:00
adapter - > curr_cmd - > resp_skb = skb ;
2011-10-11 17:41:21 -07:00
adapter - > cmd_resp_received = true ;
/* Take the pointer and set it to CMD node and will
return in the response complete callback */
card - > cmdrsp_buf = NULL ;
/* Clear the cmd-rsp buffer address in scratch registers. This
will prevent firmware from writing to the same response
buffer again . */
2013-02-08 18:18:06 -08:00
if ( mwifiex_write_reg ( adapter , reg - > cmdrsp_addr_lo , 0 ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" cmd_done: failed to clear cmd_rsp_addr_lo \n " ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
/* Write the upper 32bits of the cmdrsp buffer physical
address */
2013-02-08 18:18:06 -08:00
if ( mwifiex_write_reg ( adapter , reg - > cmdrsp_addr_hi , 0 ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" cmd_done: failed to clear cmd_rsp_addr_hi \n " ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
}
return 0 ;
}
/*
* Command Response processing complete handler
*/
static int mwifiex_pcie_cmdrsp_complete ( struct mwifiex_adapter * adapter ,
struct sk_buff * skb )
{
struct pcie_service_card * card = adapter - > card ;
if ( skb ) {
card - > cmdrsp_buf = skb ;
skb_push ( card - > cmdrsp_buf , INTF_HEADER_LEN ) ;
2013-01-03 21:21:30 -08:00
if ( mwifiex_map_pci_memory ( adapter , skb , MWIFIEX_UPLD_SIZE ,
PCI_DMA_FROMDEVICE ) )
return - 1 ;
}
2011-10-11 17:41:21 -07:00
return 0 ;
}
/*
* This function handles firmware event ready interrupt
*/
static int mwifiex_pcie_process_event_ready ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
u32 rdptr = card - > evtbd_rdptr & MWIFIEX_EVTBD_MASK ;
u32 wrptr , event ;
2013-02-08 18:18:08 -08:00
struct mwifiex_evt_buf_desc * desc ;
2013-01-03 21:21:30 -08:00
if ( ! mwifiex_pcie_ok_to_access_hw ( adapter ) )
mwifiex_pm_wakeup_card ( adapter ) ;
2011-10-11 17:41:21 -07:00
if ( adapter - > event_received ) {
2012-03-13 19:22:37 -07:00
dev_dbg ( adapter - > dev , " info: Event being processed, "
" do not process this interrupt just yet \n " ) ;
2011-10-11 17:41:21 -07:00
return 0 ;
}
if ( rdptr > = MWIFIEX_MAX_EVT_BD ) {
dev_dbg ( adapter - > dev , " info: Invalid read pointer... \n " ) ;
return - 1 ;
}
/* Read the event ring write pointer set by firmware */
2013-02-08 18:18:06 -08:00
if ( mwifiex_read_reg ( adapter , reg - > evt_wrptr , & wrptr ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
2013-02-08 18:18:06 -08:00
" EventReady: failed to read reg->evt_wrptr \n " ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
dev_dbg ( adapter - > dev , " info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x> " ,
2012-03-13 19:22:37 -07:00
card - > evtbd_rdptr , wrptr ) ;
if ( ( ( wrptr & MWIFIEX_EVTBD_MASK ) ! = ( card - > evtbd_rdptr
& MWIFIEX_EVTBD_MASK ) ) | |
2013-02-08 18:18:06 -08:00
( ( wrptr & reg - > evt_rollover_ind ) = =
( card - > evtbd_rdptr & reg - > evt_rollover_ind ) ) ) {
2011-10-11 17:41:21 -07:00
struct sk_buff * skb_cmd ;
__le16 data_len = 0 ;
u16 evt_len ;
dev_dbg ( adapter - > dev , " info: Read Index: %d \n " , rdptr ) ;
skb_cmd = card - > evt_buf_list [ rdptr ] ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb_cmd , PCI_DMA_FROMDEVICE ) ;
2013-01-03 21:21:30 -08:00
2011-10-11 17:41:21 -07:00
/* Take the pointer and set it to event pointer in adapter
and will return back after event handling callback */
card - > evt_buf_list [ rdptr ] = NULL ;
2013-02-08 18:18:08 -08:00
desc = card - > evtbd_ring [ rdptr ] ;
memset ( desc , 0 , sizeof ( * desc ) ) ;
2011-10-11 17:41:21 -07:00
event = * ( u32 * ) & skb_cmd - > data [ INTF_HEADER_LEN ] ;
adapter - > event_cause = event ;
/* The first 4bytes will be the event transfer header
len is 2 bytes followed by type which is 2 bytes */
memcpy ( & data_len , skb_cmd - > data , sizeof ( __le16 ) ) ;
evt_len = le16_to_cpu ( data_len ) ;
skb_pull ( skb_cmd , INTF_HEADER_LEN ) ;
dev_dbg ( adapter - > dev , " info: Event length: %d \n " , evt_len ) ;
if ( ( evt_len > 0 ) & & ( evt_len < MAX_EVENT_SIZE ) )
memcpy ( adapter - > event_body , skb_cmd - > data +
MWIFIEX_EVENT_HEADER_LEN , evt_len -
MWIFIEX_EVENT_HEADER_LEN ) ;
adapter - > event_received = true ;
adapter - > event_skb = skb_cmd ;
/* Do not update the event read pointer here, wait till the
buffer is released . This is just to make things simpler ,
we need to find a better method of managing these buffers .
*/
2014-09-12 20:08:49 +05:30
} else {
if ( mwifiex_write_reg ( adapter , PCIE_CPU_INT_EVENT ,
CPU_INTR_EVENT_DONE ) ) {
dev_warn ( adapter - > dev ,
" Write register failed \n " ) ;
return - 1 ;
}
2011-10-11 17:41:21 -07:00
}
return 0 ;
}
/*
* Event processing complete handler
*/
static int mwifiex_pcie_event_complete ( struct mwifiex_adapter * adapter ,
struct sk_buff * skb )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
int ret = 0 ;
u32 rdptr = card - > evtbd_rdptr & MWIFIEX_EVTBD_MASK ;
u32 wrptr ;
2013-02-08 18:18:08 -08:00
struct mwifiex_evt_buf_desc * desc ;
2011-10-11 17:41:21 -07:00
if ( ! skb )
return 0 ;
2011-11-07 19:31:47 -08:00
if ( rdptr > = MWIFIEX_MAX_EVT_BD ) {
2011-10-11 17:41:21 -07:00
dev_err ( adapter - > dev , " event_complete: Invalid rdptr 0x%x \n " ,
2012-03-13 19:22:37 -07:00
rdptr ) ;
2011-12-08 20:41:03 -08:00
return - EINVAL ;
2011-11-07 19:31:47 -08:00
}
2011-10-11 17:41:21 -07:00
/* Read the event ring write pointer set by firmware */
2013-02-08 18:18:06 -08:00
if ( mwifiex_read_reg ( adapter , reg - > evt_wrptr , & wrptr ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
2013-02-08 18:18:06 -08:00
" event_complete: failed to read reg->evt_wrptr \n " ) ;
2011-12-08 20:41:03 -08:00
return - 1 ;
2011-10-11 17:41:21 -07:00
}
if ( ! card - > evt_buf_list [ rdptr ] ) {
skb_push ( skb , INTF_HEADER_LEN ) ;
2013-01-03 21:21:30 -08:00
if ( mwifiex_map_pci_memory ( adapter , skb ,
MAX_EVENT_SIZE ,
PCI_DMA_FROMDEVICE ) )
return - 1 ;
2011-10-11 17:41:21 -07:00
card - > evt_buf_list [ rdptr ] = skb ;
2013-02-08 18:18:08 -08:00
desc = card - > evtbd_ring [ rdptr ] ;
2014-02-07 16:25:50 -08:00
desc - > paddr = MWIFIEX_SKB_DMA_ADDR ( skb ) ;
2013-02-08 18:18:08 -08:00
desc - > len = ( u16 ) skb - > len ;
desc - > flags = 0 ;
2011-10-11 17:41:21 -07:00
skb = NULL ;
} else {
2012-03-13 19:22:37 -07:00
dev_dbg ( adapter - > dev ,
" info: ERROR: buf still valid at index %d, <%p, %p> \n " ,
rdptr , card - > evt_buf_list [ rdptr ] , skb ) ;
2011-10-11 17:41:21 -07:00
}
if ( ( + + card - > evtbd_rdptr & MWIFIEX_EVTBD_MASK ) = = MWIFIEX_MAX_EVT_BD ) {
card - > evtbd_rdptr = ( ( card - > evtbd_rdptr &
2013-02-08 18:18:06 -08:00
reg - > evt_rollover_ind ) ^
reg - > evt_rollover_ind ) ;
2011-10-11 17:41:21 -07:00
}
dev_dbg ( adapter - > dev , " info: Updated <Rd: 0x%x, Wr: 0x%x> " ,
2012-03-13 19:22:37 -07:00
card - > evtbd_rdptr , wrptr ) ;
2011-10-11 17:41:21 -07:00
2013-02-08 18:18:06 -08:00
/* Write the event ring read pointer in to reg->evt_rdptr */
if ( mwifiex_write_reg ( adapter , reg - > evt_rdptr ,
card - > evtbd_rdptr ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
2013-02-08 18:18:06 -08:00
" event_complete: failed to read reg->evt_rdptr \n " ) ;
2011-12-08 20:41:03 -08:00
return - 1 ;
2011-10-11 17:41:21 -07:00
}
dev_dbg ( adapter - > dev , " info: Check Events Again \n " ) ;
ret = mwifiex_pcie_process_event_ready ( adapter ) ;
return ret ;
}
/*
* This function downloads the firmware to the card .
*
* Firmware is downloaded to the card in blocks . Every block download
* is tested for CRC errors , and retried a number of times before
* returning failure .
*/
static int mwifiex_prog_fw_w_helper ( struct mwifiex_adapter * adapter ,
struct mwifiex_fw_image * fw )
{
int ret ;
u8 * firmware = fw - > fw_buf ;
u32 firmware_len = fw - > fw_len ;
u32 offset = 0 ;
struct sk_buff * skb ;
u32 txlen , tx_blocks = 0 , tries , len ;
u32 block_retry_cnt = 0 ;
2013-01-03 21:21:30 -08:00
struct pcie_service_card * card = adapter - > card ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
if ( ! firmware | | ! firmware_len ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" No firmware image found! Terminating download \n " ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
dev_dbg ( adapter - > dev , " info: Downloading FW image (%d bytes) \n " ,
2012-03-13 19:22:37 -07:00
firmware_len ) ;
2011-10-11 17:41:21 -07:00
if ( mwifiex_pcie_disable_host_int ( adapter ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" %s: Disabling interrupts failed. \n " , __func__ ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
skb = dev_alloc_skb ( MWIFIEX_UPLD_SIZE ) ;
if ( ! skb ) {
ret = - ENOMEM ;
goto done ;
}
/* Perform firmware data transfer */
do {
u32 ireg_intr = 0 ;
/* More data? */
if ( offset > = firmware_len )
break ;
for ( tries = 0 ; tries < MAX_POLL_TRIES ; tries + + ) {
2013-02-08 18:18:06 -08:00
ret = mwifiex_read_reg ( adapter , reg - > cmd_size ,
2011-10-11 17:41:21 -07:00
& len ) ;
if ( ret ) {
2012-03-13 19:22:37 -07:00
dev_warn ( adapter - > dev ,
" Failed reading len from boot code \n " ) ;
2011-10-11 17:41:21 -07:00
goto done ;
}
if ( len )
break ;
2012-03-12 19:35:11 -07:00
usleep_range ( 10 , 20 ) ;
2011-10-11 17:41:21 -07:00
}
if ( ! len ) {
break ;
} else if ( len > MWIFIEX_UPLD_SIZE ) {
pr_err ( " FW download failure @ %d, invalid length %d \n " ,
2012-03-13 19:22:37 -07:00
offset , len ) ;
2011-10-11 17:41:21 -07:00
ret = - 1 ;
goto done ;
}
txlen = len ;
if ( len & BIT ( 0 ) ) {
block_retry_cnt + + ;
if ( block_retry_cnt > MAX_WRITE_IOMEM_RETRY ) {
pr_err ( " FW download failure @ %d, over max "
" retry count \n " , offset ) ;
ret = - 1 ;
goto done ;
}
dev_err ( adapter - > dev , " FW CRC error indicated by the "
2012-03-13 19:22:37 -07:00
" helper: len = 0x%04X, txlen = %d \n " ,
len , txlen ) ;
2011-10-11 17:41:21 -07:00
len & = ~ BIT ( 0 ) ;
/* Setting this to 0 to resend from same offset */
txlen = 0 ;
} else {
block_retry_cnt = 0 ;
/* Set blocksize to transfer - checking for
last block */
if ( firmware_len - offset < txlen )
txlen = firmware_len - offset ;
dev_dbg ( adapter - > dev , " . " ) ;
2013-02-08 18:18:06 -08:00
tx_blocks = ( txlen + card - > pcie . blksz_fw_dl - 1 ) /
card - > pcie . blksz_fw_dl ;
2011-10-11 17:41:21 -07:00
/* Copy payload to buffer */
memmove ( skb - > data , & firmware [ offset ] , txlen ) ;
}
skb_put ( skb , MWIFIEX_UPLD_SIZE - skb - > len ) ;
2013-02-08 18:18:06 -08:00
skb_trim ( skb , tx_blocks * card - > pcie . blksz_fw_dl ) ;
2011-10-11 17:41:21 -07:00
/* Send the boot command to device */
if ( mwifiex_pcie_send_boot_cmd ( adapter , skb ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" Failed to send firmware download command \n " ) ;
2011-10-11 17:41:21 -07:00
ret = - 1 ;
goto done ;
}
2013-01-03 21:21:30 -08:00
2011-10-11 17:41:21 -07:00
/* Wait for the command done interrupt */
do {
if ( mwifiex_read_reg ( adapter , PCIE_CPU_INT_STATUS ,
& ireg_intr ) ) {
dev_err ( adapter - > dev , " %s: Failed to read "
2012-03-13 19:22:37 -07:00
" interrupt status during fw dnld. \n " ,
__func__ ) ;
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb ,
PCI_DMA_TODEVICE ) ;
2011-10-11 17:41:21 -07:00
ret = - 1 ;
goto done ;
}
} while ( ( ireg_intr & CPU_INTR_DOOR_BELL ) = =
CPU_INTR_DOOR_BELL ) ;
2013-01-03 21:21:30 -08:00
2014-02-07 16:25:50 -08:00
mwifiex_unmap_pci_memory ( adapter , skb , PCI_DMA_TODEVICE ) ;
2013-01-03 21:21:30 -08:00
2011-10-11 17:41:21 -07:00
offset + = txlen ;
} while ( true ) ;
dev_dbg ( adapter - > dev , " info: \n FW download over, size %d bytes \n " ,
2012-03-13 19:22:37 -07:00
offset ) ;
2011-10-11 17:41:21 -07:00
ret = 0 ;
done :
dev_kfree_skb_any ( skb ) ;
return ret ;
}
/*
* This function checks the firmware status in card .
*
* The winner interface is also determined by this function .
*/
static int
mwifiex_check_fw_status ( struct mwifiex_adapter * adapter , u32 poll_num )
{
int ret = 0 ;
u32 firmware_stat , winner_status ;
2013-02-08 18:18:06 -08:00
struct pcie_service_card * card = adapter - > card ;
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
u32 tries ;
/* Mask spurios interrupts */
if ( mwifiex_write_reg ( adapter , PCIE_HOST_INT_STATUS_MASK ,
2012-03-13 19:22:37 -07:00
HOST_INTR_MASK ) ) {
2011-10-11 17:41:21 -07:00
dev_warn ( adapter - > dev , " Write register failed \n " ) ;
return - 1 ;
}
dev_dbg ( adapter - > dev , " Setting driver ready signature \n " ) ;
2013-02-08 18:18:06 -08:00
if ( mwifiex_write_reg ( adapter , reg - > drv_rdy ,
FIRMWARE_READY_PCIE ) ) {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" Failed to write driver ready signature \n " ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
/* Wait for firmware initialization event */
for ( tries = 0 ; tries < poll_num ; tries + + ) {
2013-02-08 18:18:06 -08:00
if ( mwifiex_read_reg ( adapter , reg - > fw_status ,
2011-10-11 17:41:21 -07:00
& firmware_stat ) )
ret = - 1 ;
else
ret = 0 ;
if ( ret )
continue ;
if ( firmware_stat = = FIRMWARE_READY_PCIE ) {
ret = 0 ;
break ;
} else {
2013-07-22 19:17:53 -07:00
msleep ( 100 ) ;
2011-10-11 17:41:21 -07:00
ret = - 1 ;
}
}
if ( ret ) {
2013-02-08 18:18:06 -08:00
if ( mwifiex_read_reg ( adapter , reg - > fw_status ,
2011-10-11 17:41:21 -07:00
& winner_status ) )
ret = - 1 ;
else if ( ! winner_status ) {
dev_err ( adapter - > dev , " PCI-E is the winner \n " ) ;
adapter - > winner = 1 ;
} else {
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" PCI-E is not the winner <%#x,%d>, exit dnld \n " ,
ret , adapter - > winner ) ;
2011-10-11 17:41:21 -07:00
}
}
return ret ;
}
/*
* This function reads the interrupt status from card .
*/
static void mwifiex_interrupt_status ( struct mwifiex_adapter * adapter )
{
u32 pcie_ireg ;
unsigned long flags ;
if ( ! mwifiex_pcie_ok_to_access_hw ( adapter ) )
return ;
if ( mwifiex_read_reg ( adapter , PCIE_HOST_INT_STATUS , & pcie_ireg ) ) {
dev_warn ( adapter - > dev , " Read register failed \n " ) ;
return ;
}
if ( ( pcie_ireg ! = 0xFFFFFFFF ) & & ( pcie_ireg ) ) {
mwifiex_pcie_disable_host_int ( adapter ) ;
/* Clear the pending interrupts */
if ( mwifiex_write_reg ( adapter , PCIE_HOST_INT_STATUS ,
~ pcie_ireg ) ) {
dev_warn ( adapter - > dev , " Write register failed \n " ) ;
return ;
}
spin_lock_irqsave ( & adapter - > int_lock , flags ) ;
adapter - > int_status | = pcie_ireg ;
spin_unlock_irqrestore ( & adapter - > int_lock , flags ) ;
2014-02-18 15:41:56 -08:00
if ( ! adapter - > pps_uapsd_mode & &
adapter - > ps_state = = PS_STATE_SLEEP & &
mwifiex_pcie_ok_to_access_hw ( adapter ) ) {
2011-10-11 17:41:21 -07:00
/* Potentially for PCIe we could get other
* interrupts like shared . Don ' t change power
* state until cookie is set */
2013-03-22 21:49:06 -07:00
adapter - > ps_state = PS_STATE_AWAKE ;
adapter - > pm_wakeup_fw_try = false ;
2011-10-11 17:41:21 -07:00
}
}
}
/*
* Interrupt handler for PCIe root port
*
* This function reads the interrupt status from firmware and assigns
* the main process in workqueue which will handle the interrupt .
*/
static irqreturn_t mwifiex_pcie_interrupt ( int irq , void * context )
{
struct pci_dev * pdev = ( struct pci_dev * ) context ;
struct pcie_service_card * card ;
struct mwifiex_adapter * adapter ;
if ( ! pdev ) {
pr_debug ( " info: %s: pdev is NULL \n " , ( u8 * ) pdev ) ;
goto exit ;
}
2013-09-09 14:26:51 +09:00
card = pci_get_drvdata ( pdev ) ;
2011-10-11 17:41:21 -07:00
if ( ! card | | ! card - > adapter ) {
pr_debug ( " info: %s: card=%p adapter=%p \n " , __func__ , card ,
2012-03-13 19:22:37 -07:00
card ? card - > adapter : NULL ) ;
2011-10-11 17:41:21 -07:00
goto exit ;
}
adapter = card - > adapter ;
if ( adapter - > surprise_removed )
goto exit ;
mwifiex_interrupt_status ( adapter ) ;
queue_work ( adapter - > workqueue , & adapter - > main_work ) ;
exit :
return IRQ_HANDLED ;
}
/*
* This function checks the current interrupt status .
*
* The following interrupts are checked and handled by this function -
* - Data sent
* - Command sent
* - Command received
* - Packets received
* - Events received
*
* In case of Rx packets received , the packets are uploaded from card to
* host and processed accordingly .
*/
static int mwifiex_process_int_status ( struct mwifiex_adapter * adapter )
{
int ret ;
2013-01-03 21:21:28 -08:00
u32 pcie_ireg ;
2011-10-11 17:41:21 -07:00
unsigned long flags ;
spin_lock_irqsave ( & adapter - > int_lock , flags ) ;
/* Clear out unused interrupts */
2013-01-03 21:21:28 -08:00
pcie_ireg = adapter - > int_status ;
adapter - > int_status = 0 ;
2011-10-11 17:41:21 -07:00
spin_unlock_irqrestore ( & adapter - > int_lock , flags ) ;
2013-01-03 21:21:28 -08:00
while ( pcie_ireg & HOST_INTR_MASK ) {
if ( pcie_ireg & HOST_INTR_DNLD_DONE ) {
pcie_ireg & = ~ HOST_INTR_DNLD_DONE ;
2013-01-03 21:21:32 -08:00
dev_dbg ( adapter - > dev , " info: TX DNLD Done \n " ) ;
ret = mwifiex_pcie_send_data_complete ( adapter ) ;
if ( ret )
return ret ;
2011-10-11 17:41:21 -07:00
}
2013-01-03 21:21:28 -08:00
if ( pcie_ireg & HOST_INTR_UPLD_RDY ) {
pcie_ireg & = ~ HOST_INTR_UPLD_RDY ;
2011-10-11 17:41:21 -07:00
dev_dbg ( adapter - > dev , " info: Rx DATA \n " ) ;
ret = mwifiex_pcie_process_recv_data ( adapter ) ;
if ( ret )
return ret ;
}
2013-01-03 21:21:28 -08:00
if ( pcie_ireg & HOST_INTR_EVENT_RDY ) {
pcie_ireg & = ~ HOST_INTR_EVENT_RDY ;
2011-10-11 17:41:21 -07:00
dev_dbg ( adapter - > dev , " info: Rx EVENT \n " ) ;
ret = mwifiex_pcie_process_event_ready ( adapter ) ;
if ( ret )
return ret ;
}
2013-01-03 21:21:28 -08:00
if ( pcie_ireg & HOST_INTR_CMD_DONE ) {
pcie_ireg & = ~ HOST_INTR_CMD_DONE ;
2011-10-11 17:41:21 -07:00
if ( adapter - > cmd_sent ) {
2012-03-13 19:22:37 -07:00
dev_dbg ( adapter - > dev ,
" info: CMD sent Interrupt \n " ) ;
2011-10-11 17:41:21 -07:00
adapter - > cmd_sent = false ;
}
/* Handle command response */
ret = mwifiex_pcie_process_cmd_complete ( adapter ) ;
if ( ret )
return ret ;
}
if ( mwifiex_pcie_ok_to_access_hw ( adapter ) ) {
if ( mwifiex_read_reg ( adapter , PCIE_HOST_INT_STATUS ,
& pcie_ireg ) ) {
2012-03-13 19:22:37 -07:00
dev_warn ( adapter - > dev ,
" Read register failed \n " ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
if ( ( pcie_ireg ! = 0xFFFFFFFF ) & & ( pcie_ireg ) ) {
if ( mwifiex_write_reg ( adapter ,
2012-03-13 19:22:37 -07:00
PCIE_HOST_INT_STATUS ,
~ pcie_ireg ) ) {
dev_warn ( adapter - > dev ,
" Write register failed \n " ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
}
}
}
dev_dbg ( adapter - > dev , " info: cmd_sent=%d data_sent=%d \n " ,
2012-03-13 19:22:37 -07:00
adapter - > cmd_sent , adapter - > data_sent ) ;
2013-03-22 21:49:05 -07:00
if ( adapter - > ps_state ! = PS_STATE_SLEEP )
mwifiex_pcie_enable_host_int ( adapter ) ;
2011-10-11 17:41:21 -07:00
return 0 ;
}
/*
* This function downloads data from driver to card .
*
* Both commands and data packets are transferred to the card by this
* function .
*
* This function adds the PCIE specific header to the front of the buffer
* before transferring . The header contains the length of the packet and
* the type . The firmware handles the packets based upon this set type .
*/
static int mwifiex_pcie_host_to_card ( struct mwifiex_adapter * adapter , u8 type ,
struct sk_buff * skb ,
struct mwifiex_tx_param * tx_param )
{
2011-11-07 19:31:45 -08:00
if ( ! skb ) {
dev_err ( adapter - > dev , " Passed NULL skb to %s \n " , __func__ ) ;
2011-10-11 17:41:21 -07:00
return - 1 ;
}
if ( type = = MWIFIEX_TYPE_DATA )
2013-01-03 21:21:32 -08:00
return mwifiex_pcie_send_data ( adapter , skb , tx_param ) ;
2011-10-11 17:41:21 -07:00
else if ( type = = MWIFIEX_TYPE_CMD )
return mwifiex_pcie_send_cmd ( adapter , skb ) ;
return 0 ;
}
2014-06-19 21:38:52 -07:00
/* This function read/write firmware */
static enum rdwr_status
mwifiex_pcie_rdwr_firmware ( struct mwifiex_adapter * adapter , u8 doneflag )
{
int ret , tries ;
u8 ctrl_data ;
struct pcie_service_card * card = adapter - > card ;
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
ret = mwifiex_write_reg ( adapter , reg - > fw_dump_ctrl , FW_DUMP_HOST_READY ) ;
if ( ret ) {
dev_err ( adapter - > dev , " PCIE write err \n " ) ;
return RDWR_STATUS_FAILURE ;
}
for ( tries = 0 ; tries < MAX_POLL_TRIES ; tries + + ) {
mwifiex_read_reg_byte ( adapter , reg - > fw_dump_ctrl , & ctrl_data ) ;
if ( ctrl_data = = FW_DUMP_DONE )
return RDWR_STATUS_SUCCESS ;
if ( doneflag & & ctrl_data = = doneflag )
return RDWR_STATUS_DONE ;
if ( ctrl_data ! = FW_DUMP_HOST_READY ) {
dev_info ( adapter - > dev ,
" The ctrl reg was changed, re-try again! \n " ) ;
2014-09-18 08:04:01 -04:00
ret = mwifiex_write_reg ( adapter , reg - > fw_dump_ctrl ,
FW_DUMP_HOST_READY ) ;
2014-06-19 21:38:52 -07:00
if ( ret ) {
dev_err ( adapter - > dev , " PCIE write err \n " ) ;
return RDWR_STATUS_FAILURE ;
}
}
usleep_range ( 100 , 200 ) ;
}
dev_err ( adapter - > dev , " Fail to pull ctrl_data \n " ) ;
return RDWR_STATUS_FAILURE ;
}
/* This function dump firmware memory to file */
static void mwifiex_pcie_fw_dump_work ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
const struct mwifiex_pcie_card_reg * creg = card - > pcie . reg ;
unsigned int reg , reg_start , reg_end ;
u8 * dbg_ptr , * end_ptr , dump_num , idx , i , read_reg , doneflag = 0 ;
enum rdwr_status stat ;
u32 memory_size ;
2014-09-18 08:04:01 -04:00
int ret ;
2014-06-19 21:38:52 -07:00
static char * env [ ] = { " DRIVER=mwifiex_pcie " , " EVENT=fw_dump " , NULL } ;
if ( ! card - > pcie . supports_fw_dump )
return ;
for ( idx = 0 ; idx < ARRAY_SIZE ( mem_type_mapping_tbl ) ; idx + + ) {
struct memory_type_mapping * entry = & mem_type_mapping_tbl [ idx ] ;
if ( entry - > mem_ptr ) {
vfree ( entry - > mem_ptr ) ;
entry - > mem_ptr = NULL ;
}
entry - > mem_size = 0 ;
}
2014-07-17 15:55:09 -07:00
dev_info ( adapter - > dev , " == mwifiex firmware dump start == \n " ) ;
2014-06-19 21:38:52 -07:00
/* Read the number of the memories which will dump */
stat = mwifiex_pcie_rdwr_firmware ( adapter , doneflag ) ;
if ( stat = = RDWR_STATUS_FAILURE )
goto done ;
reg = creg - > fw_dump_start ;
mwifiex_read_reg_byte ( adapter , reg , & dump_num ) ;
/* Read the length of every memory which will dump */
for ( idx = 0 ; idx < dump_num ; idx + + ) {
struct memory_type_mapping * entry = & mem_type_mapping_tbl [ idx ] ;
stat = mwifiex_pcie_rdwr_firmware ( adapter , doneflag ) ;
if ( stat = = RDWR_STATUS_FAILURE )
goto done ;
memory_size = 0 ;
reg = creg - > fw_dump_start ;
for ( i = 0 ; i < 4 ; i + + ) {
mwifiex_read_reg_byte ( adapter , reg , & read_reg ) ;
memory_size | = ( read_reg < < ( i * 8 ) ) ;
reg + + ;
}
if ( memory_size = = 0 ) {
dev_info ( adapter - > dev , " Firmware dump Finished! \n " ) ;
2014-09-18 07:18:50 -04:00
ret = mwifiex_write_reg ( adapter , creg - > fw_dump_ctrl ,
FW_DUMP_READ_DONE ) ;
if ( ret ) {
dev_err ( adapter - > dev , " PCIE write err \n " ) ;
goto done ;
}
2014-06-19 21:38:52 -07:00
break ;
}
dev_info ( adapter - > dev ,
" %s_SIZE=0x%x \n " , entry - > mem_name , memory_size ) ;
entry - > mem_ptr = vmalloc ( memory_size + 1 ) ;
entry - > mem_size = memory_size ;
if ( ! entry - > mem_ptr ) {
dev_err ( adapter - > dev ,
" Vmalloc %s failed \n " , entry - > mem_name ) ;
goto done ;
}
dbg_ptr = entry - > mem_ptr ;
end_ptr = dbg_ptr + memory_size ;
doneflag = entry - > done_flag ;
2014-07-17 15:55:09 -07:00
dev_info ( adapter - > dev , " Start %s output, please wait... \n " ,
entry - > mem_name ) ;
2014-06-19 21:38:52 -07:00
do {
stat = mwifiex_pcie_rdwr_firmware ( adapter , doneflag ) ;
if ( RDWR_STATUS_FAILURE = = stat )
goto done ;
reg_start = creg - > fw_dump_start ;
reg_end = creg - > fw_dump_end ;
for ( reg = reg_start ; reg < = reg_end ; reg + + ) {
mwifiex_read_reg_byte ( adapter , reg , dbg_ptr ) ;
2014-09-18 08:04:01 -04:00
if ( dbg_ptr < end_ptr ) {
2014-06-19 21:38:52 -07:00
dbg_ptr + + ;
2014-09-18 08:04:01 -04:00
} else {
2014-06-19 21:38:52 -07:00
dev_err ( adapter - > dev ,
" Allocated buf not enough \n " ) ;
2014-09-18 08:04:01 -04:00
goto done ;
}
2014-06-19 21:38:52 -07:00
}
if ( stat ! = RDWR_STATUS_DONE )
continue ;
dev_info ( adapter - > dev , " %s done: size=0x%tx \n " ,
entry - > mem_name , dbg_ptr - entry - > mem_ptr ) ;
break ;
} while ( true ) ;
}
2014-07-17 15:55:09 -07:00
dev_info ( adapter - > dev , " == mwifiex firmware dump end == \n " ) ;
2014-06-19 21:38:52 -07:00
kobject_uevent_env ( & adapter - > wiphy - > dev . kobj , KOBJ_CHANGE , env ) ;
done :
adapter - > curr_mem_idx = 0 ;
}
static void mwifiex_pcie_work ( struct work_struct * work )
{
struct mwifiex_adapter * adapter =
container_of ( work , struct mwifiex_adapter , iface_work ) ;
if ( test_and_clear_bit ( MWIFIEX_IFACE_WORK_FW_DUMP ,
& adapter - > iface_work_flags ) )
mwifiex_pcie_fw_dump_work ( adapter ) ;
}
/* This function dumps FW information */
static void mwifiex_pcie_fw_dump ( struct mwifiex_adapter * adapter )
{
if ( test_bit ( MWIFIEX_IFACE_WORK_FW_DUMP , & adapter - > iface_work_flags ) )
return ;
set_bit ( MWIFIEX_IFACE_WORK_FW_DUMP , & adapter - > iface_work_flags ) ;
schedule_work ( & adapter - > iface_work ) ;
}
2011-10-11 17:41:21 -07:00
/*
* This function initializes the PCI - E host memory space , WCB rings , etc .
*
* The following initializations steps are followed -
* - Allocate TXBD ring buffers
* - Allocate RXBD ring buffers
* - Allocate event BD ring buffers
* - Allocate command response ring buffer
* - Allocate sleep cookie buffer
*/
static int mwifiex_pcie_init ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
int ret ;
struct pci_dev * pdev = card - > dev ;
2013-02-12 14:38:32 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
pci_set_drvdata ( pdev , card ) ;
ret = pci_enable_device ( pdev ) ;
if ( ret )
goto err_enable_dev ;
pci_set_master ( pdev ) ;
dev_dbg ( adapter - > dev , " try set_consistent_dma_mask(32) \n " ) ;
ret = pci_set_dma_mask ( pdev , DMA_BIT_MASK ( 32 ) ) ;
if ( ret ) {
dev_err ( adapter - > dev , " set_dma_mask(32) failed \n " ) ;
goto err_set_dma_mask ;
}
ret = pci_set_consistent_dma_mask ( pdev , DMA_BIT_MASK ( 32 ) ) ;
if ( ret ) {
dev_err ( adapter - > dev , " set_consistent_dma_mask(64) failed \n " ) ;
goto err_set_dma_mask ;
}
ret = pci_request_region ( pdev , 0 , DRV_NAME ) ;
if ( ret ) {
dev_err ( adapter - > dev , " req_reg(0) error \n " ) ;
goto err_req_region0 ;
}
card - > pci_mmap = pci_iomap ( pdev , 0 , 0 ) ;
if ( ! card - > pci_mmap ) {
dev_err ( adapter - > dev , " iomap(0) error \n " ) ;
2013-01-26 00:56:03 +04:00
ret = - EIO ;
2011-10-11 17:41:21 -07:00
goto err_iomap0 ;
}
ret = pci_request_region ( pdev , 2 , DRV_NAME ) ;
if ( ret ) {
dev_err ( adapter - > dev , " req_reg(2) error \n " ) ;
goto err_req_region2 ;
}
card - > pci_mmap1 = pci_iomap ( pdev , 2 , 0 ) ;
if ( ! card - > pci_mmap1 ) {
dev_err ( adapter - > dev , " iomap(2) error \n " ) ;
2013-01-26 00:56:03 +04:00
ret = - EIO ;
2011-10-11 17:41:21 -07:00
goto err_iomap2 ;
}
2012-03-13 19:22:37 -07:00
dev_dbg ( adapter - > dev ,
" PCI memory map Virt0: %p PCI memory map Virt2: %p \n " ,
card - > pci_mmap , card - > pci_mmap1 ) ;
2011-10-11 17:41:21 -07:00
card - > cmdrsp_buf = NULL ;
ret = mwifiex_pcie_create_txbd_ring ( adapter ) ;
if ( ret )
goto err_cre_txbd ;
ret = mwifiex_pcie_create_rxbd_ring ( adapter ) ;
if ( ret )
goto err_cre_rxbd ;
ret = mwifiex_pcie_create_evtbd_ring ( adapter ) ;
if ( ret )
goto err_cre_evtbd ;
ret = mwifiex_pcie_alloc_cmdrsp_buf ( adapter ) ;
if ( ret )
goto err_alloc_cmdbuf ;
2013-02-12 14:38:32 -08:00
if ( reg - > sleep_cookie ) {
ret = mwifiex_pcie_alloc_sleep_cookie_buf ( adapter ) ;
if ( ret )
goto err_alloc_cookie ;
} else {
card - > sleep_cookie_vbase = NULL ;
}
2011-10-11 17:41:21 -07:00
return ret ;
err_alloc_cookie :
mwifiex_pcie_delete_cmdrsp_buf ( adapter ) ;
err_alloc_cmdbuf :
mwifiex_pcie_delete_evtbd_ring ( adapter ) ;
err_cre_evtbd :
mwifiex_pcie_delete_rxbd_ring ( adapter ) ;
err_cre_rxbd :
mwifiex_pcie_delete_txbd_ring ( adapter ) ;
err_cre_txbd :
pci_iounmap ( pdev , card - > pci_mmap1 ) ;
err_iomap2 :
pci_release_region ( pdev , 2 ) ;
err_req_region2 :
pci_iounmap ( pdev , card - > pci_mmap ) ;
err_iomap0 :
pci_release_region ( pdev , 0 ) ;
err_req_region0 :
err_set_dma_mask :
pci_disable_device ( pdev ) ;
err_enable_dev :
pci_set_drvdata ( pdev , NULL ) ;
return ret ;
}
/*
* This function cleans up the allocated card buffers .
*
* The following are freed by this function -
* - TXBD ring buffers
* - RXBD ring buffers
* - Event BD ring buffers
* - Command response ring buffer
* - Sleep cookie buffer
*/
static void mwifiex_pcie_cleanup ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
struct pci_dev * pdev = card - > dev ;
2013-02-08 18:18:06 -08:00
const struct mwifiex_pcie_card_reg * reg = card - > pcie . reg ;
2011-10-11 17:41:21 -07:00
if ( user_rmmod ) {
2013-01-03 21:21:30 -08:00
dev_dbg ( adapter - > dev , " Clearing driver ready signature \n " ) ;
2013-02-08 18:18:06 -08:00
if ( mwifiex_write_reg ( adapter , reg - > drv_rdy , 0x00000000 ) )
2012-03-13 19:22:37 -07:00
dev_err ( adapter - > dev ,
" Failed to write driver not-ready signature \n " ) ;
2011-10-11 17:41:21 -07:00
}
if ( pdev ) {
pci_iounmap ( pdev , card - > pci_mmap ) ;
pci_iounmap ( pdev , card - > pci_mmap1 ) ;
2013-04-23 16:49:48 -07:00
pci_disable_device ( pdev ) ;
2013-04-23 16:49:47 -07:00
pci_release_region ( pdev , 2 ) ;
pci_release_region ( pdev , 0 ) ;
2011-10-11 17:41:21 -07:00
pci_set_drvdata ( pdev , NULL ) ;
}
2013-11-14 19:10:41 -08:00
kfree ( card ) ;
2011-10-11 17:41:21 -07:00
}
/*
* This function registers the PCIE device .
*
* PCIE IRQ is claimed , block size is set and driver data is initialized .
*/
static int mwifiex_register_dev ( struct mwifiex_adapter * adapter )
{
int ret ;
struct pcie_service_card * card = adapter - > card ;
struct pci_dev * pdev = card - > dev ;
/* save adapter pointer in card */
card - > adapter = adapter ;
ret = request_irq ( pdev - > irq , mwifiex_pcie_interrupt , IRQF_SHARED ,
" MRVL_PCIE " , pdev ) ;
if ( ret ) {
pr_err ( " request_irq failed: ret=%d \n " , ret ) ;
adapter - > card = NULL ;
return - 1 ;
}
adapter - > dev = & pdev - > dev ;
2014-02-27 19:35:13 -08:00
adapter - > tx_buf_size = card - > pcie . tx_buf_size ;
2014-06-19 21:38:52 -07:00
adapter - > mem_type_mapping_tbl = mem_type_mapping_tbl ;
adapter - > num_mem_types = ARRAY_SIZE ( mem_type_mapping_tbl ) ;
2013-02-08 18:18:06 -08:00
strcpy ( adapter - > fw_name , card - > pcie . firmware ) ;
2011-10-11 17:41:21 -07:00
return 0 ;
}
/*
* This function unregisters the PCIE device .
*
* The PCIE IRQ is released , the function is disabled and driver
* data is set to null .
*/
static void mwifiex_unregister_dev ( struct mwifiex_adapter * adapter )
{
struct pcie_service_card * card = adapter - > card ;
2013-02-12 14:38:32 -08:00
const struct mwifiex_pcie_card_reg * reg ;
2011-10-11 17:41:21 -07:00
if ( card ) {
dev_dbg ( adapter - > dev , " %s(): calling free_irq() \n " , __func__ ) ;
free_irq ( card - > dev - > irq , card - > dev ) ;
2013-01-03 21:21:30 -08:00
2013-02-12 14:38:32 -08:00
reg = card - > pcie . reg ;
if ( reg - > sleep_cookie )
mwifiex_pcie_delete_sleep_cookie_buf ( adapter ) ;
2013-01-03 21:21:30 -08:00
mwifiex_pcie_delete_cmdrsp_buf ( adapter ) ;
mwifiex_pcie_delete_evtbd_ring ( adapter ) ;
mwifiex_pcie_delete_rxbd_ring ( adapter ) ;
mwifiex_pcie_delete_txbd_ring ( adapter ) ;
card - > cmdrsp_buf = NULL ;
2011-10-11 17:41:21 -07:00
}
}
static struct mwifiex_if_ops pcie_ops = {
. init_if = mwifiex_pcie_init ,
. cleanup_if = mwifiex_pcie_cleanup ,
. check_fw_status = mwifiex_check_fw_status ,
. prog_fw = mwifiex_prog_fw_w_helper ,
. register_dev = mwifiex_register_dev ,
. unregister_dev = mwifiex_unregister_dev ,
. enable_int = mwifiex_pcie_enable_host_int ,
. process_int_status = mwifiex_process_int_status ,
. host_to_card = mwifiex_pcie_host_to_card ,
. wakeup = mwifiex_pm_wakeup_card ,
. wakeup_complete = mwifiex_pm_wakeup_card_complete ,
/* PCIE specific */
. cmdrsp_complete = mwifiex_pcie_cmdrsp_complete ,
. event_complete = mwifiex_pcie_event_complete ,
. update_mp_end_port = NULL ,
. cleanup_mpa_buf = NULL ,
2013-01-03 21:21:29 -08:00
. init_fw_port = mwifiex_pcie_init_fw_port ,
2013-01-03 21:21:31 -08:00
. clean_pcie_ring = mwifiex_clean_pcie_ring_buf ,
2014-06-19 21:38:52 -07:00
. fw_dump = mwifiex_pcie_fw_dump ,
. iface_work = mwifiex_pcie_work ,
2011-10-11 17:41:21 -07:00
} ;
/*
* This function initializes the PCIE driver module .
*
* This initiates the semaphore and registers the device with
* PCIE bus .
*/
static int mwifiex_pcie_init_module ( void )
{
int ret ;
2013-02-08 18:18:09 -08:00
pr_debug ( " Marvell PCIe Driver \n " ) ;
2011-10-11 17:41:21 -07:00
sema_init ( & add_remove_card_sem , 1 ) ;
/* Clear the flag in case user removes the card. */
user_rmmod = 0 ;
ret = pci_register_driver ( & mwifiex_pcie ) ;
if ( ret )
pr_err ( " Driver register failed! \n " ) ;
else
pr_debug ( " info: Driver registered successfully! \n " ) ;
return ret ;
}
/*
* This function cleans up the PCIE driver .
*
* The following major steps are followed for cleanup -
* - Resume the device if its suspended
* - Disconnect the device if connected
* - Shutdown the firmware
* - Unregister the device from PCIE bus .
*/
static void mwifiex_pcie_cleanup_module ( void )
{
if ( ! down_interruptible ( & add_remove_card_sem ) )
up ( & add_remove_card_sem ) ;
/* Set the flag as user is removing this module. */
user_rmmod = 1 ;
pci_unregister_driver ( & mwifiex_pcie ) ;
}
module_init ( mwifiex_pcie_init_module ) ;
module_exit ( mwifiex_pcie_cleanup_module ) ;
MODULE_AUTHOR ( " Marvell International Ltd. " ) ;
MODULE_DESCRIPTION ( " Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION ) ;
MODULE_VERSION ( PCIE_VERSION ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
2013-02-08 18:18:09 -08:00
MODULE_FIRMWARE ( PCIE8766_DEFAULT_FW_NAME ) ;
MODULE_FIRMWARE ( PCIE8897_DEFAULT_FW_NAME ) ;