2007-05-08 04:33:32 +04:00
/*
* Copyright ( C ) 2005 - 2007 Kristian Hoegsberg < krh @ bitplanet . net >
2006-12-20 03:58:27 +03:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
2008-05-24 18:50:22 +04:00
# include <linux/completion.h>
# include <linux/crc-itu-t.h>
2008-02-28 00:14:27 +03:00
# include <linux/delay.h>
2006-12-20 03:58:27 +03:00
# include <linux/device.h>
2008-05-24 18:50:22 +04:00
# include <linux/errno.h>
# include <linux/kref.h>
# include <linux/module.h>
2007-05-08 04:33:33 +04:00
# include <linux/mutex.h>
2008-05-24 18:50:22 +04:00
2006-12-20 03:58:27 +03:00
# include "fw-transaction.h"
# include "fw-topology.h"
2006-12-20 03:58:31 +03:00
# include "fw-device.h"
2006-12-20 03:58:27 +03:00
2007-05-08 04:33:31 +04:00
int fw_compute_block_crc ( u32 * block )
2006-12-20 03:58:27 +03:00
{
2007-05-08 04:33:31 +04:00
__be32 be32_block [ 256 ] ;
int i , length ;
length = ( * block > > 16 ) & 0xff ;
for ( i = 0 ; i < length ; i + + )
be32_block [ i ] = cpu_to_be32 ( block [ i + 1 ] ) ;
* block | = crc_itu_t ( 0 , ( u8 * ) be32_block , length * 4 ) ;
2006-12-20 03:58:27 +03:00
2007-05-08 04:33:31 +04:00
return length ;
2006-12-20 03:58:27 +03:00
}
2007-05-08 04:33:33 +04:00
static DEFINE_MUTEX ( card_mutex ) ;
2006-12-20 03:58:27 +03:00
static LIST_HEAD ( card_list ) ;
static LIST_HEAD ( descriptor_list ) ;
static int descriptor_count ;
2007-05-08 04:33:35 +04:00
# define BIB_CRC(v) ((v) << 0)
# define BIB_CRC_LENGTH(v) ((v) << 16)
# define BIB_INFO_LENGTH(v) ((v) << 24)
# define BIB_LINK_SPEED(v) ((v) << 0)
# define BIB_GENERATION(v) ((v) << 4)
# define BIB_MAX_ROM(v) ((v) << 8)
# define BIB_MAX_RECEIVE(v) ((v) << 12)
# define BIB_CYC_CLK_ACC(v) ((v) << 16)
# define BIB_PMC ((1) << 27)
# define BIB_BMC ((1) << 28)
# define BIB_ISC ((1) << 29)
# define BIB_CMC ((1) << 30)
# define BIB_IMC ((1) << 31)
2006-12-20 03:58:27 +03:00
static u32 *
2007-05-08 04:33:34 +04:00
generate_config_rom ( struct fw_card * card , size_t * config_rom_length )
2006-12-20 03:58:27 +03:00
{
struct fw_descriptor * desc ;
static u32 config_rom [ 256 ] ;
int i , j , length ;
2007-05-08 04:33:32 +04:00
/*
* Initialize contents of config rom buffer . On the OHCI
2007-01-21 22:44:09 +03:00
* controller , block reads to the config rom accesses the host
* memory , but quadlet read access the hardware bus info block
* registers . That ' s just crack , but it means we should make
2008-10-22 23:59:42 +04:00
* sure the contents of bus info block in host memory matches
2007-05-08 04:33:32 +04:00
* the version stored in the OHCI registers .
*/
2006-12-20 03:58:27 +03:00
2007-05-10 03:23:14 +04:00
memset ( config_rom , 0 , sizeof ( config_rom ) ) ;
2007-05-08 04:33:35 +04:00
config_rom [ 0 ] = BIB_CRC_LENGTH ( 4 ) | BIB_INFO_LENGTH ( 4 ) | BIB_CRC ( 0 ) ;
2006-12-20 03:58:27 +03:00
config_rom [ 1 ] = 0x31333934 ;
config_rom [ 2 ] =
2007-05-08 04:33:35 +04:00
BIB_LINK_SPEED ( card - > link_speed ) |
BIB_GENERATION ( card - > config_rom_generation + + % 14 + 2 ) |
BIB_MAX_ROM ( 2 ) |
BIB_MAX_RECEIVE ( card - > max_receive ) |
BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC ;
2006-12-20 03:58:27 +03:00
config_rom [ 3 ] = card - > guid > > 32 ;
config_rom [ 4 ] = card - > guid ;
/* Generate root directory. */
i = 5 ;
config_rom [ i + + ] = 0 ;
config_rom [ i + + ] = 0x0c0083c0 ; /* node capabilities */
j = i + descriptor_count ;
/* Generate root directory entries for descriptors. */
list_for_each_entry ( desc , & descriptor_list , link ) {
2007-03-07 20:12:36 +03:00
if ( desc - > immediate > 0 )
config_rom [ i + + ] = desc - > immediate ;
2006-12-20 03:58:27 +03:00
config_rom [ i ] = desc - > key | ( j - i ) ;
i + + ;
j + = desc - > length ;
}
/* Update root directory length. */
config_rom [ 5 ] = ( i - 5 - 1 ) < < 16 ;
/* End of root directory, now copy in descriptors. */
list_for_each_entry ( desc , & descriptor_list , link ) {
memcpy ( & config_rom [ i ] , desc - > data , desc - > length * 4 ) ;
i + = desc - > length ;
}
/* Calculate CRCs for all blocks in the config rom. This
* assumes that CRC length and info length are identical for
* the bus info block , which is always the case for this
* implementation . */
2007-05-08 04:33:31 +04:00
for ( i = 0 ; i < j ; i + = length + 1 )
length = fw_compute_block_crc ( config_rom + i ) ;
2006-12-20 03:58:27 +03:00
* config_rom_length = j ;
return config_rom ;
}
static void
2007-05-08 04:33:34 +04:00
update_config_roms ( void )
2006-12-20 03:58:27 +03:00
{
struct fw_card * card ;
u32 * config_rom ;
size_t length ;
list_for_each_entry ( card , & card_list , link ) {
config_rom = generate_config_rom ( card , & length ) ;
card - > driver - > set_config_rom ( card , config_rom , length ) ;
}
}
int
2007-05-08 04:33:34 +04:00
fw_core_add_descriptor ( struct fw_descriptor * desc )
2006-12-20 03:58:27 +03:00
{
size_t i ;
2007-05-08 04:33:32 +04:00
/*
* Check descriptor is valid ; the length of all blocks in the
2006-12-20 03:58:27 +03:00
* descriptor has to add up to exactly the length of the
2007-05-08 04:33:32 +04:00
* block .
*/
2006-12-20 03:58:27 +03:00
i = 0 ;
while ( i < desc - > length )
i + = ( desc - > data [ i ] > > 16 ) + 1 ;
if ( i ! = desc - > length )
2007-03-28 23:26:42 +04:00
return - EINVAL ;
2006-12-20 03:58:27 +03:00
2007-05-08 04:33:33 +04:00
mutex_lock ( & card_mutex ) ;
2006-12-20 03:58:27 +03:00
2007-05-08 04:33:34 +04:00
list_add_tail ( & desc - > link , & descriptor_list ) ;
2006-12-20 03:58:27 +03:00
descriptor_count + + ;
2007-03-07 20:12:36 +03:00
if ( desc - > immediate > 0 )
descriptor_count + + ;
2006-12-20 03:58:27 +03:00
update_config_roms ( ) ;
2007-05-08 04:33:33 +04:00
mutex_unlock ( & card_mutex ) ;
2006-12-20 03:58:27 +03:00
return 0 ;
}
void
2007-05-08 04:33:34 +04:00
fw_core_remove_descriptor ( struct fw_descriptor * desc )
2006-12-20 03:58:27 +03:00
{
2007-05-08 04:33:33 +04:00
mutex_lock ( & card_mutex ) ;
2006-12-20 03:58:27 +03:00
list_del ( & desc - > link ) ;
descriptor_count - - ;
2007-03-07 20:12:36 +03:00
if ( desc - > immediate > 0 )
descriptor_count - - ;
2006-12-20 03:58:27 +03:00
update_config_roms ( ) ;
2007-05-08 04:33:33 +04:00
mutex_unlock ( & card_mutex ) ;
2006-12-20 03:58:27 +03:00
}
2007-01-26 08:37:50 +03:00
static const char gap_count_table [ ] = {
63 , 5 , 7 , 8 , 10 , 13 , 16 , 18 , 21 , 24 , 26 , 29 , 32 , 35 , 37 , 40
} ;
2008-11-29 19:44:57 +03:00
void
fw_schedule_bm_work ( struct fw_card * card , unsigned long delay )
{
int scheduled ;
fw_card_get ( card ) ;
scheduled = schedule_delayed_work ( & card - > work , delay ) ;
if ( ! scheduled )
fw_card_put ( card ) ;
}
2007-01-26 08:38:45 +03:00
static void
fw_card_bm_work ( struct work_struct * work )
2006-12-20 03:58:31 +03:00
{
2007-01-26 08:37:50 +03:00
struct fw_card * card = container_of ( work , struct fw_card , work . work ) ;
2008-02-24 20:57:23 +03:00
struct fw_device * root_device ;
struct fw_node * root_node , * local_node ;
2006-12-20 03:58:31 +03:00
unsigned long flags ;
2008-07-20 16:20:53 +04:00
int root_id , new_root_id , irm_id , gap_count , generation , grace , rcode ;
2008-03-24 22:57:12 +03:00
bool do_reset = false ;
2009-01-09 22:49:37 +03:00
bool root_device_is_running ;
bool root_device_is_cmc ;
2008-07-20 16:20:53 +04:00
__be32 lock_data [ 2 ] ;
2006-12-20 03:58:31 +03:00
spin_lock_irqsave ( & card - > lock , flags ) ;
2008-02-24 20:57:23 +03:00
local_node = card - > local_node ;
root_node = card - > root_node ;
if ( local_node = = NULL ) {
spin_unlock_irqrestore ( & card - > lock , flags ) ;
2008-11-29 19:44:57 +03:00
goto out_put_card ;
2008-02-24 20:57:23 +03:00
}
fw_node_get ( local_node ) ;
fw_node_get ( root_node ) ;
2006-12-20 03:58:31 +03:00
generation = card - > generation ;
2008-02-24 20:57:23 +03:00
root_device = root_node - > data ;
2009-01-09 22:49:37 +03:00
root_device_is_running = root_device & &
atomic_read ( & root_device - > state ) = = FW_DEVICE_RUNNING ;
root_device_is_cmc = root_device & & root_device - > cmc ;
2008-02-24 20:57:23 +03:00
root_id = root_node - > node_id ;
2007-01-26 08:38:45 +03:00
grace = time_after ( jiffies , card - > reset_jiffies + DIV_ROUND_UP ( HZ , 10 ) ) ;
2008-03-24 22:56:40 +03:00
if ( is_next_generation ( generation , card - > bm_generation ) | |
2007-01-26 08:38:45 +03:00
( card - > bm_generation ! = generation & & grace ) ) {
2007-05-08 04:33:32 +04:00
/*
* This first step is to figure out who is IRM and
2007-01-26 08:38:45 +03:00
* then try to become bus manager . If the IRM is not
* well defined ( e . g . does not have an active link
* layer or does not responds to our lock request , we
* will have to do a little vigilante bus management .
* In that case , we do a goto into the gap count logic
* so that when we do the reset , we still optimize the
* gap count . That could well save a reset in the
2007-05-08 04:33:32 +04:00
* next generation .
*/
2007-01-26 08:38:45 +03:00
irm_id = card - > irm_node - > node_id ;
if ( ! card - > irm_node - > link_on ) {
2008-02-24 20:57:23 +03:00
new_root_id = local_node - > node_id ;
2007-01-26 08:38:45 +03:00
fw_notify ( " IRM has link off, making local node (%02x) root. \n " ,
new_root_id ) ;
goto pick_me ;
}
2008-07-20 16:20:53 +04:00
lock_data [ 0 ] = cpu_to_be32 ( 0x3f ) ;
lock_data [ 1 ] = cpu_to_be32 ( local_node - > node_id ) ;
2007-01-26 08:38:45 +03:00
spin_unlock_irqrestore ( & card - > lock , flags ) ;
2008-07-20 16:20:53 +04:00
rcode = fw_run_transaction ( card , TCODE_LOCK_COMPARE_SWAP ,
irm_id , generation , SCODE_100 ,
CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID ,
lock_data , sizeof ( lock_data ) ) ;
2007-01-26 08:38:45 +03:00
2008-07-20 16:20:53 +04:00
if ( rcode = = RCODE_GENERATION )
/* Another bus reset, BM work has been rescheduled. */
2008-02-24 20:57:23 +03:00
goto out ;
2007-01-26 08:38:45 +03:00
2008-07-20 16:20:53 +04:00
if ( rcode = = RCODE_COMPLETE & &
lock_data [ 0 ] ! = cpu_to_be32 ( 0x3f ) )
2007-01-26 08:38:45 +03:00
/* Somebody else is BM, let them do the work. */
2008-02-24 20:57:23 +03:00
goto out ;
2007-01-26 08:38:45 +03:00
spin_lock_irqsave ( & card - > lock , flags ) ;
2008-07-20 16:20:53 +04:00
if ( rcode ! = RCODE_COMPLETE ) {
2007-05-08 04:33:32 +04:00
/*
* The lock request failed , maybe the IRM
2007-01-26 08:38:45 +03:00
* isn ' t really IRM capable after all . Let ' s
* do a bus reset and pick the local node as
2007-05-08 04:33:32 +04:00
* root , and thus , IRM .
*/
2008-02-24 20:57:23 +03:00
new_root_id = local_node - > node_id ;
2007-01-26 08:38:45 +03:00
fw_notify ( " BM lock failed, making local node (%02x) root. \n " ,
new_root_id ) ;
goto pick_me ;
}
} else if ( card - > bm_generation ! = generation ) {
2007-05-08 04:33:32 +04:00
/*
* OK , we weren ' t BM in the last generation , and it ' s
2007-01-26 08:38:45 +03:00
* less than 100 ms since last bus reset . Reschedule
2007-05-08 04:33:32 +04:00
* this task 100 ms from now .
*/
2007-01-26 08:38:45 +03:00
spin_unlock_irqrestore ( & card - > lock , flags ) ;
2008-11-29 19:44:57 +03:00
fw_schedule_bm_work ( card , DIV_ROUND_UP ( HZ , 10 ) ) ;
2008-02-24 20:57:23 +03:00
goto out ;
2007-01-26 08:38:45 +03:00
}
2007-05-08 04:33:32 +04:00
/*
* We ' re bus manager for this generation , so next step is to
2007-01-26 08:38:45 +03:00
* make sure we have an active cycle master and do gap count
2007-05-08 04:33:32 +04:00
* optimization .
*/
2007-01-26 08:38:45 +03:00
card - > bm_generation = generation ;
2006-12-20 03:58:31 +03:00
2008-02-24 20:57:23 +03:00
if ( root_device = = NULL ) {
2007-05-08 04:33:32 +04:00
/*
* Either link_on is false , or we failed to read the
* config rom . In either case , pick another root .
*/
2008-02-24 20:57:23 +03:00
new_root_id = local_node - > node_id ;
2009-01-09 22:49:37 +03:00
} else if ( ! root_device_is_running ) {
2007-05-08 04:33:32 +04:00
/*
* If we haven ' t probed this device yet , bail out now
* and let ' s try again once that ' s done .
*/
2007-01-26 08:38:45 +03:00
spin_unlock_irqrestore ( & card - > lock , flags ) ;
2008-02-24 20:57:23 +03:00
goto out ;
2009-01-09 22:49:37 +03:00
} else if ( root_device_is_cmc ) {
2007-05-08 04:33:32 +04:00
/*
* FIXME : I suppose we should set the cmstr bit in the
2006-12-20 03:58:31 +03:00
* STATE_CLEAR register of this node , as described in
* 1394 - 1995 , 8.4 .2 .6 . Also , send out a force root
2007-05-08 04:33:32 +04:00
* packet for this node .
*/
2007-01-26 08:38:45 +03:00
new_root_id = root_id ;
2007-01-26 08:37:50 +03:00
} else {
2007-05-08 04:33:32 +04:00
/*
* Current root has an active link layer and we
2006-12-20 03:58:31 +03:00
* successfully read the config rom , but it ' s not
2007-05-08 04:33:32 +04:00
* cycle master capable .
*/
2008-02-24 20:57:23 +03:00
new_root_id = local_node - > node_id ;
2007-01-26 08:37:50 +03:00
}
2007-01-26 08:38:45 +03:00
pick_me :
2007-06-18 21:44:12 +04:00
/*
* Pick a gap count from 1394 a table E - 1. The table doesn ' t cover
* the typically much larger 1394 b beta repeater delays though .
*/
if ( ! card - > beta_repeaters_present & &
2008-02-24 20:57:23 +03:00
root_node - > max_hops < ARRAY_SIZE ( gap_count_table ) )
gap_count = gap_count_table [ root_node - > max_hops ] ;
2007-01-26 08:37:50 +03:00
else
gap_count = 63 ;
2007-05-08 04:33:32 +04:00
/*
2008-03-24 22:57:12 +03:00
* Finally , figure out if we should do a reset or not . If we have
* done less than 5 resets with the same physical topology and we
2007-05-08 04:33:32 +04:00
* have either a new root or a new gap count setting , let ' s do it .
*/
2006-12-20 03:58:31 +03:00
2007-01-26 08:38:45 +03:00
if ( card - > bm_retries + + < 5 & &
( card - > gap_count ! = gap_count | | new_root_id ! = root_id ) )
2008-03-24 22:57:12 +03:00
do_reset = true ;
2006-12-20 03:58:31 +03:00
spin_unlock_irqrestore ( & card - > lock , flags ) ;
2007-01-26 08:37:50 +03:00
if ( do_reset ) {
fw_notify ( " phy config: card %d, new root=%x, gap_count=%d \n " ,
2007-01-26 08:38:45 +03:00
card - > index , new_root_id , gap_count ) ;
fw_send_phy_config ( card , new_root_id , generation , gap_count ) ;
2006-12-20 03:58:31 +03:00
fw_core_initiate_bus_reset ( card , 1 ) ;
}
2008-02-24 20:57:23 +03:00
out :
fw_node_put ( root_node ) ;
fw_node_put ( local_node ) ;
2008-11-29 19:44:57 +03:00
out_put_card :
fw_card_put ( card ) ;
2006-12-20 03:58:31 +03:00
}
2006-12-20 03:58:27 +03:00
static void
flush_timer_callback ( unsigned long data )
{
struct fw_card * card = ( struct fw_card * ) data ;
fw_flush_transactions ( card ) ;
}
void
2007-01-14 17:29:07 +03:00
fw_card_initialize ( struct fw_card * card , const struct fw_card_driver * driver ,
2006-12-20 03:58:27 +03:00
struct device * device )
{
2007-02-06 22:49:38 +03:00
static atomic_t index = ATOMIC_INIT ( - 1 ) ;
2006-12-20 03:58:27 +03:00
2007-02-06 22:49:38 +03:00
card - > index = atomic_inc_return ( & index ) ;
2007-01-21 22:44:09 +03:00
card - > driver = driver ;
2006-12-20 03:58:27 +03:00
card - > device = device ;
2007-01-21 22:44:09 +03:00
card - > current_tlabel = 0 ;
card - > tlabel_mask = 0 ;
2006-12-20 03:58:27 +03:00
card - > color = 0 ;
2008-05-24 18:41:09 +04:00
card - > broadcast_channel = BROADCAST_CHANNEL_INITIAL ;
2006-12-20 03:58:27 +03:00
2008-05-24 18:50:22 +04:00
kref_init ( & card - > kref ) ;
init_completion ( & card - > done ) ;
2007-01-21 22:44:09 +03:00
INIT_LIST_HEAD ( & card - > transaction_list ) ;
2006-12-20 03:58:27 +03:00
spin_lock_init ( & card - > lock ) ;
setup_timer ( & card - > flush_timer ,
flush_timer_callback , ( unsigned long ) card ) ;
card - > local_node = NULL ;
2007-01-26 08:38:45 +03:00
INIT_DELAYED_WORK ( & card - > work , fw_card_bm_work ) ;
2006-12-20 03:58:27 +03:00
}
EXPORT_SYMBOL ( fw_card_initialize ) ;
int
fw_card_add ( struct fw_card * card ,
u32 max_receive , u32 link_speed , u64 guid )
{
u32 * config_rom ;
size_t length ;
card - > max_receive = max_receive ;
card - > link_speed = link_speed ;
card - > guid = guid ;
2007-05-08 04:33:33 +04:00
mutex_lock ( & card_mutex ) ;
2007-05-08 04:33:34 +04:00
config_rom = generate_config_rom ( card , & length ) ;
2006-12-20 03:58:27 +03:00
list_add_tail ( & card - > link , & card_list ) ;
2007-05-08 04:33:33 +04:00
mutex_unlock ( & card_mutex ) ;
2006-12-20 03:58:27 +03:00
return card - > driver - > enable ( card , config_rom , length ) ;
}
EXPORT_SYMBOL ( fw_card_add ) ;
2007-05-08 04:33:32 +04:00
/*
* The next few functions implements a dummy driver that use once a
2006-12-20 03:58:27 +03:00
* card driver shuts down an fw_card . This allows the driver to
* cleanly unload , as all IO to the card will be handled by the dummy
* driver instead of calling into the ( possibly ) unloaded module . The
2007-05-08 04:33:32 +04:00
* dummy driver just fails all IO .
*/
2006-12-20 03:58:27 +03:00
static int
dummy_enable ( struct fw_card * card , u32 * config_rom , size_t length )
{
BUG ( ) ;
return - 1 ;
}
static int
dummy_update_phy_reg ( struct fw_card * card , int address ,
int clear_bits , int set_bits )
{
return - ENODEV ;
}
static int
dummy_set_config_rom ( struct fw_card * card ,
u32 * config_rom , size_t length )
{
2007-05-08 04:33:32 +04:00
/*
* We take the card out of card_list before setting the dummy
* driver , so this should never get called .
*/
2006-12-20 03:58:27 +03:00
BUG ( ) ;
return - 1 ;
}
static void
dummy_send_request ( struct fw_card * card , struct fw_packet * packet )
{
2007-01-21 22:44:09 +03:00
packet - > callback ( packet , card , - ENODEV ) ;
2006-12-20 03:58:27 +03:00
}
static void
dummy_send_response ( struct fw_card * card , struct fw_packet * packet )
{
2007-01-21 22:44:09 +03:00
packet - > callback ( packet , card , - ENODEV ) ;
2006-12-20 03:58:27 +03:00
}
2007-02-06 22:49:32 +03:00
static int
dummy_cancel_packet ( struct fw_card * card , struct fw_packet * packet )
{
return - ENOENT ;
}
2006-12-20 03:58:27 +03:00
static int
dummy_enable_phys_dma ( struct fw_card * card ,
int node_id , int generation )
{
return - ENODEV ;
}
static struct fw_card_driver dummy_driver = {
. enable = dummy_enable ,
. update_phy_reg = dummy_update_phy_reg ,
. set_config_rom = dummy_set_config_rom ,
2007-01-21 22:44:09 +03:00
. send_request = dummy_send_request ,
2007-02-06 22:49:32 +03:00
. cancel_packet = dummy_cancel_packet ,
2007-01-21 22:44:09 +03:00
. send_response = dummy_send_response ,
2007-01-21 22:45:32 +03:00
. enable_phys_dma = dummy_enable_phys_dma ,
2006-12-20 03:58:27 +03:00
} ;
2008-05-24 18:50:22 +04:00
void
fw_card_release ( struct kref * kref )
{
struct fw_card * card = container_of ( kref , struct fw_card , kref ) ;
complete ( & card - > done ) ;
}
2006-12-20 03:58:27 +03:00
void
fw_core_remove_card ( struct fw_card * card )
{
2007-03-23 19:24:02 +03:00
card - > driver - > update_phy_reg ( card , 4 ,
PHY_LINK_ACTIVE | PHY_CONTENDER , 0 ) ;
2006-12-20 03:58:27 +03:00
fw_core_initiate_bus_reset ( card , 1 ) ;
2007-05-08 04:33:33 +04:00
mutex_lock ( & card_mutex ) ;
2006-12-20 03:58:27 +03:00
list_del ( & card - > link ) ;
2007-05-08 04:33:33 +04:00
mutex_unlock ( & card_mutex ) ;
2006-12-20 03:58:27 +03:00
/* Set up the dummy driver. */
card - > driver = & dummy_driver ;
fw_destroy_nodes ( card ) ;
2008-05-24 18:50:22 +04:00
/* Wait for all users, especially device workqueue jobs, to finish. */
fw_card_put ( card ) ;
wait_for_completion ( & card - > done ) ;
2007-08-21 03:05:14 +04:00
2008-07-12 16:51:18 +04:00
WARN_ON ( ! list_empty ( & card - > transaction_list ) ) ;
2007-08-21 03:05:14 +04:00
del_timer_sync ( & card - > flush_timer ) ;
2006-12-20 03:58:27 +03:00
}
EXPORT_SYMBOL ( fw_core_remove_card ) ;
int
fw_core_initiate_bus_reset ( struct fw_card * card , int short_reset )
{
2007-03-23 19:24:02 +03:00
int reg = short_reset ? 5 : 1 ;
int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET ;
return card - > driver - > update_phy_reg ( card , reg , 0 , bit ) ;
2006-12-20 03:58:27 +03:00
}
EXPORT_SYMBOL ( fw_core_initiate_bus_reset ) ;