2006-12-19 19:58:27 -05:00
/* -*- c-basic-offset: 8 -*-
*
* fw - card . c - card level functions
*
* Copyright ( C ) 2005 - 2006 Kristian Hoegsberg < krh @ bitplanet . net >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
# include <linux/module.h>
# include <linux/errno.h>
# include <linux/device.h>
# include "fw-transaction.h"
# include "fw-topology.h"
2006-12-19 19:58:31 -05:00
# include "fw-device.h"
2006-12-19 19:58:27 -05:00
/* The lib/crc16.c implementation uses the standard (0x8005)
* polynomial , but we need the ITU - T ( or CCITT ) polynomial ( 0x1021 ) .
* The implementation below works on an array of host - endian u32
* words , assuming they ' ll be transmited msb first . */
2007-03-07 12:12:55 -05:00
u16
2006-12-19 19:58:27 -05:00
crc16_itu_t ( const u32 * buffer , size_t length )
{
int shift , i ;
u32 data ;
u16 sum , crc = 0 ;
for ( i = 0 ; i < length ; i + + ) {
data = * buffer + + ;
for ( shift = 28 ; shift > = 0 ; shift - = 4 ) {
sum = ( ( crc > > 12 ) ^ ( data > > shift ) ) & 0xf ;
crc = ( crc < < 4 ) ^ ( sum < < 12 ) ^ ( sum < < 5 ) ^ ( sum ) ;
}
crc & = 0xffff ;
}
return crc ;
}
static LIST_HEAD ( card_list ) ;
static LIST_HEAD ( descriptor_list ) ;
static int descriptor_count ;
# 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)
static u32 *
generate_config_rom ( struct fw_card * card , size_t * config_rom_length )
{
struct fw_descriptor * desc ;
static u32 config_rom [ 256 ] ;
int i , j , length ;
2007-01-21 20:44:09 +01:00
/* Initialize contents of config rom buffer. On the OHCI
* 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
* sure the contents of bus info block in host memory mathces
* the version stored in the OHCI registers . */
2006-12-19 19:58:27 -05:00
memset ( config_rom , 0 , sizeof config_rom ) ;
config_rom [ 0 ] = bib_crc_length ( 4 ) | bib_info_length ( 4 ) | bib_crc ( 0 ) ;
config_rom [ 1 ] = 0x31333934 ;
config_rom [ 2 ] =
bib_link_speed ( card - > link_speed ) |
bib_generation ( card - > config_rom_generation + + % 14 + 2 ) |
bib_max_rom ( 2 ) |
bib_max_receive ( card - > max_receive ) |
2007-01-26 00:38:45 -05:00
bib_bmc | bib_isc | bib_cmc | bib_imc ;
2006-12-19 19:58:27 -05: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 12:12:36 -05:00
if ( desc - > immediate > 0 )
config_rom [ i + + ] = desc - > immediate ;
2006-12-19 19:58:27 -05: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 . */
for ( i = 0 ; i < j ; i + = length + 1 ) {
length = ( config_rom [ i ] > > 16 ) & 0xff ;
config_rom [ i ] | = crc16_itu_t ( & config_rom [ i + 1 ] , length ) ;
}
* config_rom_length = j ;
return config_rom ;
}
static void
update_config_roms ( void )
{
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
fw_core_add_descriptor ( struct fw_descriptor * desc )
{
size_t i ;
/* Check descriptor is valid; the length of all blocks in the
* descriptor has to add up to exactly the length of the
* block . */
i = 0 ;
while ( i < desc - > length )
i + = ( desc - > data [ i ] > > 16 ) + 1 ;
if ( i ! = desc - > length )
return - 1 ;
down_write ( & fw_bus_type . subsys . rwsem ) ;
list_add_tail ( & desc - > link , & descriptor_list ) ;
descriptor_count + + ;
2007-03-07 12:12:36 -05:00
if ( desc - > immediate > 0 )
descriptor_count + + ;
2006-12-19 19:58:27 -05:00
update_config_roms ( ) ;
up_write ( & fw_bus_type . subsys . rwsem ) ;
return 0 ;
}
EXPORT_SYMBOL ( fw_core_add_descriptor ) ;
void
fw_core_remove_descriptor ( struct fw_descriptor * desc )
{
down_write ( & fw_bus_type . subsys . rwsem ) ;
list_del ( & desc - > link ) ;
descriptor_count - - ;
2007-03-07 12:12:36 -05:00
if ( desc - > immediate > 0 )
descriptor_count - - ;
2006-12-19 19:58:27 -05:00
update_config_roms ( ) ;
up_write ( & fw_bus_type . subsys . rwsem ) ;
}
EXPORT_SYMBOL ( fw_core_remove_descriptor ) ;
2007-01-26 00:37:50 -05:00
static const char gap_count_table [ ] = {
63 , 5 , 7 , 8 , 10 , 13 , 16 , 18 , 21 , 24 , 26 , 29 , 32 , 35 , 37 , 40
} ;
2007-01-26 00:38:45 -05:00
struct bm_data {
struct fw_transaction t ;
struct {
__be32 arg ;
__be32 data ;
} lock ;
u32 old ;
int rcode ;
struct completion done ;
} ;
2006-12-19 19:58:31 -05:00
static void
2007-01-26 00:38:45 -05:00
complete_bm_lock ( struct fw_card * card , int rcode ,
void * payload , size_t length , void * data )
{
struct bm_data * bmd = data ;
if ( rcode = = RCODE_COMPLETE )
bmd - > old = be32_to_cpu ( * ( __be32 * ) payload ) ;
bmd - > rcode = rcode ;
complete ( & bmd - > done ) ;
}
static void
fw_card_bm_work ( struct work_struct * work )
2006-12-19 19:58:31 -05:00
{
2007-01-26 00:37:50 -05:00
struct fw_card * card = container_of ( work , struct fw_card , work . work ) ;
2006-12-19 19:58:31 -05:00
struct fw_device * root ;
2007-01-26 00:38:45 -05:00
struct bm_data bmd ;
2006-12-19 19:58:31 -05:00
unsigned long flags ;
2007-01-26 00:38:45 -05:00
int root_id , new_root_id , irm_id , gap_count , generation , grace ;
int do_reset = 0 ;
2006-12-19 19:58:31 -05:00
spin_lock_irqsave ( & card - > lock , flags ) ;
generation = card - > generation ;
root = card - > root_node - > data ;
2007-01-26 00:37:50 -05:00
root_id = card - > root_node - > node_id ;
2007-01-26 00:38:45 -05:00
grace = time_after ( jiffies , card - > reset_jiffies + DIV_ROUND_UP ( HZ , 10 ) ) ;
if ( card - > bm_generation + 1 = = generation | |
( card - > bm_generation ! = generation & & grace ) ) {
/* This first step is to figure out who is IRM and
* 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
* next generation . */
irm_id = card - > irm_node - > node_id ;
if ( ! card - > irm_node - > link_on ) {
new_root_id = card - > local_node - > node_id ;
fw_notify ( " IRM has link off, making local node (%02x) root. \n " ,
new_root_id ) ;
goto pick_me ;
}
bmd . lock . arg = cpu_to_be32 ( 0x3f ) ;
bmd . lock . data = cpu_to_be32 ( card - > local_node - > node_id ) ;
spin_unlock_irqrestore ( & card - > lock , flags ) ;
init_completion ( & bmd . done ) ;
fw_send_request ( card , & bmd . t , TCODE_LOCK_COMPARE_SWAP ,
irm_id , generation ,
SCODE_100 , CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID ,
& bmd . lock , sizeof bmd . lock ,
complete_bm_lock , & bmd ) ;
wait_for_completion ( & bmd . done ) ;
if ( bmd . rcode = = RCODE_GENERATION ) {
/* Another bus reset happened. Just return,
* the BM work has been rescheduled . */
return ;
}
if ( bmd . rcode = = RCODE_COMPLETE & & bmd . old ! = 0x3f )
/* Somebody else is BM, let them do the work. */
return ;
spin_lock_irqsave ( & card - > lock , flags ) ;
if ( bmd . rcode ! = RCODE_COMPLETE ) {
/* The lock request failed, maybe the IRM
* isn ' t really IRM capable after all . Let ' s
* do a bus reset and pick the local node as
* root , and thus , IRM . */
new_root_id = card - > local_node - > node_id ;
fw_notify ( " BM lock failed, making local node (%02x) root. \n " ,
new_root_id ) ;
goto pick_me ;
}
} else if ( card - > bm_generation ! = generation ) {
/* OK, we weren't BM in the last generation, and it's
* less than 100 ms since last bus reset . Reschedule
* this task 100 ms from now . */
spin_unlock_irqrestore ( & card - > lock , flags ) ;
schedule_delayed_work ( & card - > work , DIV_ROUND_UP ( HZ , 10 ) ) ;
return ;
}
/* We're bus manager for this generation, so next step is to
* make sure we have an active cycle master and do gap count
* optimization . */
card - > bm_generation = generation ;
2006-12-19 19:58:31 -05:00
2007-01-26 00:37:50 -05:00
if ( root = = NULL ) {
2006-12-19 19:58:31 -05:00
/* Either link_on is false, or we failed to read the
* config rom . In either case , pick another root . */
2007-01-26 00:38:45 -05:00
new_root_id = card - > local_node - > node_id ;
2007-01-27 10:34:55 +01:00
} else if ( atomic_read ( & root - > state ) ! = FW_DEVICE_RUNNING ) {
2006-12-19 19:58:31 -05:00
/* If we haven't probed this device yet, bail out now
* and let ' s try again once that ' s done . */
2007-01-26 00:38:45 -05:00
spin_unlock_irqrestore ( & card - > lock , flags ) ;
return ;
2007-01-26 00:37:50 -05:00
} else if ( root - > config_rom [ 2 ] & bib_cmc ) {
2006-12-19 19:58:31 -05:00
/* FIXME: I suppose we should set the cmstr bit in the
* STATE_CLEAR register of this node , as described in
* 1394 - 1995 , 8.4 .2 .6 . Also , send out a force root
* packet for this node . */
2007-01-26 00:38:45 -05:00
new_root_id = root_id ;
2007-01-26 00:37:50 -05:00
} else {
2006-12-19 19:58:31 -05:00
/* Current root has an active link layer and we
* successfully read the config rom , but it ' s not
* cycle master capable . */
2007-01-26 00:38:45 -05:00
new_root_id = card - > local_node - > node_id ;
2007-01-26 00:37:50 -05:00
}
2007-01-26 00:38:45 -05:00
pick_me :
2007-01-26 00:37:50 -05:00
/* Now figure out what gap count to set. */
if ( card - > topology_type = = FW_TOPOLOGY_A & &
card - > root_node - > max_hops < ARRAY_SIZE ( gap_count_table ) )
gap_count = gap_count_table [ card - > root_node - > max_hops ] ;
else
gap_count = 63 ;
/* Finally, figure out if we should do a reset or not. If we've
* done less that 5 resets with the same physical topology and we
* have either a new root or a new gap count setting , let ' s do it . */
2006-12-19 19:58:31 -05:00
2007-01-26 00:38:45 -05:00
if ( card - > bm_retries + + < 5 & &
( card - > gap_count ! = gap_count | | new_root_id ! = root_id ) )
2007-01-26 00:37:50 -05:00
do_reset = 1 ;
2006-12-19 19:58:31 -05:00
spin_unlock_irqrestore ( & card - > lock , flags ) ;
2007-01-26 00:37:50 -05:00
if ( do_reset ) {
fw_notify ( " phy config: card %d, new root=%x, gap_count=%d \n " ,
2007-01-26 00:38:45 -05:00
card - > index , new_root_id , gap_count ) ;
fw_send_phy_config ( card , new_root_id , generation , gap_count ) ;
2006-12-19 19:58:31 -05:00
fw_core_initiate_bus_reset ( card , 1 ) ;
}
}
2006-12-19 19:58:27 -05: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 15:29:07 +01:00
fw_card_initialize ( struct fw_card * card , const struct fw_card_driver * driver ,
2006-12-19 19:58:27 -05:00
struct device * device )
{
2007-02-06 14:49:38 -05:00
static atomic_t index = ATOMIC_INIT ( - 1 ) ;
2006-12-19 19:58:27 -05:00
2007-03-07 12:12:37 -05:00
kref_init ( & card - > kref ) ;
2007-02-06 14:49:38 -05:00
card - > index = atomic_inc_return ( & index ) ;
2007-01-21 20:44:09 +01:00
card - > driver = driver ;
2006-12-19 19:58:27 -05:00
card - > device = device ;
2007-01-21 20:44:09 +01:00
card - > current_tlabel = 0 ;
card - > tlabel_mask = 0 ;
2006-12-19 19:58:27 -05:00
card - > color = 0 ;
2007-01-21 20:44:09 +01:00
INIT_LIST_HEAD ( & card - > transaction_list ) ;
2006-12-19 19:58:27 -05:00
spin_lock_init ( & card - > lock ) ;
setup_timer ( & card - > flush_timer ,
flush_timer_callback , ( unsigned long ) card ) ;
card - > local_node = NULL ;
2007-01-26 00:38:45 -05:00
INIT_DELAYED_WORK ( & card - > work , fw_card_bm_work ) ;
2006-12-19 19:58:27 -05: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 ;
/* FIXME: add #define's for phy registers. */
/* Activate link_on bit and contender bit in our self ID packets.*/
if ( card - > driver - > update_phy_reg ( card , 4 , 0 , 0x80 | 0x40 ) < 0 )
return - EIO ;
/* The subsystem grabs a reference when the card is added and
* drops it when the driver calls fw_core_remove_card . */
fw_card_get ( card ) ;
down_write ( & fw_bus_type . subsys . rwsem ) ;
config_rom = generate_config_rom ( card , & length ) ;
list_add_tail ( & card - > link , & card_list ) ;
up_write ( & fw_bus_type . subsys . rwsem ) ;
return card - > driver - > enable ( card , config_rom , length ) ;
}
EXPORT_SYMBOL ( fw_card_add ) ;
/* The next few functions implements a dummy driver that use once a
* 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
* dummy driver just fails all IO . */
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 )
{
/* We take the card out of card_list before setting the dummy
* driver , so this should never get called . */
BUG ( ) ;
return - 1 ;
}
static void
dummy_send_request ( struct fw_card * card , struct fw_packet * packet )
{
2007-01-21 20:44:09 +01:00
packet - > callback ( packet , card , - ENODEV ) ;
2006-12-19 19:58:27 -05:00
}
static void
dummy_send_response ( struct fw_card * card , struct fw_packet * packet )
{
2007-01-21 20:44:09 +01:00
packet - > callback ( packet , card , - ENODEV ) ;
2006-12-19 19:58:27 -05:00
}
2007-02-06 14:49:32 -05:00
static int
dummy_cancel_packet ( struct fw_card * card , struct fw_packet * packet )
{
return - ENOENT ;
}
2006-12-19 19:58:27 -05: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 = {
2007-01-21 20:44:09 +01:00
. name = " dummy " ,
2006-12-19 19:58:27 -05:00
. enable = dummy_enable ,
. update_phy_reg = dummy_update_phy_reg ,
. set_config_rom = dummy_set_config_rom ,
2007-01-21 20:44:09 +01:00
. send_request = dummy_send_request ,
2007-02-06 14:49:32 -05:00
. cancel_packet = dummy_cancel_packet ,
2007-01-21 20:44:09 +01:00
. send_response = dummy_send_response ,
2007-01-21 20:45:32 +01:00
. enable_phys_dma = dummy_enable_phys_dma ,
2006-12-19 19:58:27 -05:00
} ;
void
fw_core_remove_card ( struct fw_card * card )
{
card - > driver - > update_phy_reg ( card , 4 , 0x80 | 0x40 , 0 ) ;
fw_core_initiate_bus_reset ( card , 1 ) ;
down_write ( & fw_bus_type . subsys . rwsem ) ;
list_del ( & card - > link ) ;
up_write ( & fw_bus_type . subsys . rwsem ) ;
/* Set up the dummy driver. */
card - > driver = & dummy_driver ;
fw_flush_transactions ( card ) ;
fw_destroy_nodes ( card ) ;
2007-03-07 12:12:37 -05:00
fw_card_put ( card ) ;
2006-12-19 19:58:27 -05:00
}
EXPORT_SYMBOL ( fw_core_remove_card ) ;
struct fw_card *
fw_card_get ( struct fw_card * card )
{
2007-03-07 12:12:37 -05:00
kref_get ( & card - > kref ) ;
2006-12-19 19:58:27 -05:00
return card ;
}
EXPORT_SYMBOL ( fw_card_get ) ;
2007-03-07 12:12:37 -05:00
static void
release_card ( struct kref * kref )
{
struct fw_card * card = container_of ( kref , struct fw_card , kref ) ;
kfree ( card ) ;
}
2006-12-19 19:58:27 -05:00
/* An assumption for fw_card_put() is that the card driver allocates
* the fw_card struct with kalloc and that it has been shut down
* before the last ref is dropped . */
void
fw_card_put ( struct fw_card * card )
{
2007-03-07 12:12:37 -05:00
kref_put ( & card - > kref , release_card ) ;
2006-12-19 19:58:27 -05:00
}
EXPORT_SYMBOL ( fw_card_put ) ;
int
fw_core_initiate_bus_reset ( struct fw_card * card , int short_reset )
{
2007-01-21 20:44:09 +01:00
return card - > driver - > update_phy_reg ( card , short_reset ? 5 : 1 , 0 , 0x40 ) ;
2006-12-19 19:58:27 -05:00
}
EXPORT_SYMBOL ( fw_core_initiate_bus_reset ) ;