2005-04-17 02:20:36 +04:00
/*
2005-05-20 22:33:25 +04:00
* w1 . c
2005-04-17 02:20:36 +04:00
*
2011-08-26 02:59:06 +04:00
* Copyright ( c ) 2004 Evgeniy Polyakov < zbr @ ioremap . net >
2005-05-20 22:33:25 +04:00
*
2005-04-17 02:20:36 +04: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
*/
# include <linux/delay.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/list.h>
# include <linux/interrupt.h>
# include <linux/spinlock.h>
# include <linux/timer.h>
# include <linux/device.h>
# include <linux/slab.h>
# include <linux/sched.h>
2006-02-20 11:15:37 +03:00
# include <linux/kthread.h>
2006-12-07 07:34:23 +03:00
# include <linux/freezer.h>
2005-04-17 02:20:36 +04:00
2011-07-27 03:09:06 +04:00
# include <linux/atomic.h>
2005-04-17 02:20:36 +04:00
# include "w1.h"
# include "w1_log.h"
# include "w1_int.h"
# include "w1_family.h"
# include "w1_netlink.h"
MODULE_LICENSE ( " GPL " ) ;
2011-08-26 02:59:06 +04:00
MODULE_AUTHOR ( " Evgeniy Polyakov <zbr@ioremap.net> " ) ;
2005-04-17 02:20:36 +04:00
MODULE_DESCRIPTION ( " Driver for 1-wire Dallas network protocol. " ) ;
static int w1_timeout = 10 ;
2014-01-16 08:29:15 +04:00
int w1_max_slave_count = 64 ;
2005-04-17 02:20:36 +04:00
int w1_max_slave_ttl = 10 ;
module_param_named ( timeout , w1_timeout , int , 0 ) ;
2014-01-16 08:29:25 +04:00
MODULE_PARM_DESC ( timeout , " time in seconds between automatic slave searches " ) ;
/* A search stops when w1_max_slave_count devices have been found in that
* search . The next search will start over and detect the same set of devices
* on a static 1 - wire bus . Memory is not allocated based on this number , just
* on the number of devices known to the kernel . Having a high number does not
* consume additional resources . As a special case , if there is only one
* device on the network and w1_max_slave_count is set to 1 , the device id can
* be read directly skipping the normal slower search process .
*/
2005-04-17 02:20:36 +04:00
module_param_named ( max_slave_count , w1_max_slave_count , int , 0 ) ;
2014-01-16 08:29:25 +04:00
MODULE_PARM_DESC ( max_slave_count ,
" maximum number of slaves detected in a search " ) ;
2005-04-17 02:20:36 +04:00
module_param_named ( slave_ttl , w1_max_slave_ttl , int , 0 ) ;
2014-01-16 08:29:25 +04:00
MODULE_PARM_DESC ( slave_ttl ,
" Number of searches not seeing a slave before it will be removed " ) ;
2005-04-17 02:20:36 +04:00
2006-04-03 12:04:27 +04:00
DEFINE_MUTEX ( w1_mlock ) ;
2005-04-17 02:20:36 +04:00
LIST_HEAD ( w1_masters ) ;
static int w1_master_match ( struct device * dev , struct device_driver * drv )
{
return 1 ;
}
static int w1_master_probe ( struct device * dev )
{
return - ENODEV ;
}
static void w1_master_release ( struct device * dev )
{
2005-08-11 17:27:49 +04:00
struct w1_master * md = dev_to_w1_master ( dev ) ;
2005-08-11 17:27:50 +04:00
dev_dbg ( dev , " %s: Releasing %s. \n " , __func__ , md - > name ) ;
memset ( md , 0 , sizeof ( struct w1_master ) + sizeof ( struct w1_bus_master ) ) ;
kfree ( md ) ;
2005-04-17 02:20:36 +04:00
}
static void w1_slave_release ( struct device * dev )
{
2005-08-11 17:27:49 +04:00
struct w1_slave * sl = dev_to_w1_slave ( dev ) ;
2005-08-11 17:27:50 +04:00
2014-01-16 08:29:18 +04:00
dev_dbg ( dev , " %s: Releasing %s [%p] \n " , __func__ , sl - > name , sl ) ;
2005-08-11 17:27:50 +04:00
w1_family_put ( sl - > family ) ;
sl - > master - > slave_count - - ;
2005-04-17 02:20:36 +04:00
}
2013-08-22 00:24:33 +04:00
static ssize_t name_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2005-08-11 17:27:50 +04:00
struct w1_slave * sl = dev_to_w1_slave ( dev ) ;
2005-08-11 17:27:50 +04:00
2005-08-11 17:27:50 +04:00
return sprintf ( buf , " %s \n " , sl - > name ) ;
2005-04-17 02:20:36 +04:00
}
2013-08-22 00:24:33 +04:00
static DEVICE_ATTR_RO ( name ) ;
2005-04-17 02:20:36 +04:00
2013-08-22 00:24:33 +04:00
static ssize_t id_show ( struct device * dev ,
2008-10-16 09:04:50 +04:00
struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2008-10-16 09:04:50 +04:00
struct w1_slave * sl = dev_to_w1_slave ( dev ) ;
ssize_t count = sizeof ( sl - > reg_num ) ;
2005-08-11 17:27:50 +04:00
2008-10-16 09:04:50 +04:00
memcpy ( buf , ( u8 * ) & sl - > reg_num , count ) ;
2005-08-11 17:27:50 +04:00
return count ;
2005-08-11 17:27:50 +04:00
}
2013-08-22 00:24:33 +04:00
static DEVICE_ATTR_RO ( id ) ;
2005-08-11 17:27:50 +04:00
2013-08-22 00:24:33 +04:00
static struct attribute * w1_slave_attrs [ ] = {
& dev_attr_name . attr ,
& dev_attr_id . attr ,
NULL ,
} ;
ATTRIBUTE_GROUPS ( w1_slave ) ;
2005-05-20 22:33:25 +04:00
2005-08-11 17:27:50 +04:00
/* Default family */
2006-03-23 19:11:58 +03:00
2013-08-22 02:44:55 +04:00
static ssize_t rw_write ( struct file * filp , struct kobject * kobj ,
struct bin_attribute * bin_attr , char * buf , loff_t off ,
size_t count )
2006-03-23 19:11:58 +03:00
{
struct w1_slave * sl = kobj_to_w1_slave ( kobj ) ;
2006-04-03 12:04:27 +04:00
mutex_lock ( & sl - > master - > mutex ) ;
2006-03-23 19:11:58 +03:00
if ( w1_reset_select_slave ( sl ) ) {
count = 0 ;
goto out_up ;
}
w1_write_block ( sl - > master , buf , count ) ;
out_up :
2006-04-03 12:04:27 +04:00
mutex_unlock ( & sl - > master - > mutex ) ;
2006-03-23 19:11:58 +03:00
return count ;
}
2013-08-22 02:44:55 +04:00
static ssize_t rw_read ( struct file * filp , struct kobject * kobj ,
struct bin_attribute * bin_attr , char * buf , loff_t off ,
size_t count )
2006-03-23 19:11:58 +03:00
{
struct w1_slave * sl = kobj_to_w1_slave ( kobj ) ;
2006-04-03 12:04:27 +04:00
mutex_lock ( & sl - > master - > mutex ) ;
2006-03-23 19:11:58 +03:00
w1_read_block ( sl - > master , buf , count ) ;
2006-04-03 12:04:27 +04:00
mutex_unlock ( & sl - > master - > mutex ) ;
2006-03-23 19:11:58 +03:00
return count ;
}
2013-08-22 02:44:55 +04:00
static BIN_ATTR_RW ( rw , PAGE_SIZE ) ;
static struct bin_attribute * w1_slave_bin_attrs [ ] = {
& bin_attr_rw ,
NULL ,
2006-03-23 19:11:58 +03:00
} ;
2013-08-22 02:44:55 +04:00
static const struct attribute_group w1_slave_default_group = {
. bin_attrs = w1_slave_bin_attrs ,
} ;
2006-03-23 19:11:58 +03:00
2013-08-22 02:44:55 +04:00
static const struct attribute_group * w1_slave_default_groups [ ] = {
& w1_slave_default_group ,
NULL ,
} ;
2006-03-23 19:11:58 +03:00
static struct w1_family_ops w1_default_fops = {
2013-08-22 02:44:55 +04:00
. groups = w1_slave_default_groups ,
2006-03-23 19:11:58 +03:00
} ;
static struct w1_family w1_default_family = {
. fops = & w1_default_fops ,
} ;
2005-08-11 17:27:50 +04:00
2007-08-14 17:15:12 +04:00
static int w1_uevent ( struct device * dev , struct kobj_uevent_env * env ) ;
2005-05-20 22:33:25 +04:00
2005-04-17 02:20:36 +04:00
static struct bus_type w1_bus_type = {
. name = " w1 " ,
. match = w1_master_match ,
2005-11-16 11:00:00 +03:00
. uevent = w1_uevent ,
2005-04-17 02:20:36 +04:00
} ;
2005-08-11 13:20:07 +04:00
struct device_driver w1_master_driver = {
. name = " w1_master_driver " ,
2005-04-17 02:20:36 +04:00
. bus = & w1_bus_type ,
. probe = w1_master_probe ,
} ;
2005-08-11 13:20:07 +04:00
struct device w1_master_device = {
2005-04-17 02:20:36 +04:00
. parent = NULL ,
. bus = & w1_bus_type ,
2009-01-06 21:44:34 +03:00
. init_name = " w1 bus master " ,
2005-08-11 13:20:07 +04:00
. driver = & w1_master_driver ,
2005-04-17 02:20:36 +04:00
. release = & w1_master_release
} ;
2006-04-04 20:35:22 +04:00
static struct device_driver w1_slave_driver = {
2005-08-11 13:20:07 +04:00
. name = " w1_slave_driver " ,
. bus = & w1_bus_type ,
} ;
2006-04-04 20:35:22 +04:00
#if 0
2005-08-11 13:20:07 +04:00
struct device w1_slave_device = {
. parent = NULL ,
. bus = & w1_bus_type ,
2009-01-06 21:44:34 +03:00
. init_name = " w1 bus slave " ,
2005-08-11 13:20:07 +04:00
. driver = & w1_slave_driver ,
2005-08-11 17:27:50 +04:00
. release = & w1_slave_release
2005-08-11 13:20:07 +04:00
} ;
2006-04-04 20:35:22 +04:00
# endif /* 0 */
2005-08-11 13:20:07 +04:00
2005-05-17 14:44:04 +04:00
static ssize_t w1_master_attribute_show_name ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2005-08-11 17:27:49 +04:00
struct w1_master * md = dev_to_w1_master ( dev ) ;
2005-04-17 02:20:36 +04:00
ssize_t count ;
2005-05-20 22:33:25 +04:00
2006-04-03 12:04:27 +04:00
mutex_lock ( & md - > mutex ) ;
2005-04-17 02:20:36 +04:00
count = sprintf ( buf , " %s \n " , md - > name ) ;
2006-04-03 12:04:27 +04:00
mutex_unlock ( & md - > mutex ) ;
2005-04-17 02:20:36 +04:00
return count ;
}
2005-06-04 01:31:02 +04:00
static ssize_t w1_master_attribute_store_search ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
{
2008-10-16 09:04:42 +04:00
long tmp ;
2005-08-11 17:27:49 +04:00
struct w1_master * md = dev_to_w1_master ( dev ) ;
2013-09-12 01:26:03 +04:00
int ret ;
2005-06-04 01:31:02 +04:00
2013-09-12 01:26:03 +04:00
ret = kstrtol ( buf , 0 , & tmp ) ;
if ( ret )
return ret ;
2008-10-16 09:04:42 +04:00
2006-04-03 12:04:27 +04:00
mutex_lock ( & md - > mutex ) ;
2008-10-16 09:04:42 +04:00
md - > search_count = tmp ;
2006-04-03 12:04:27 +04:00
mutex_unlock ( & md - > mutex ) ;
2014-01-16 08:29:14 +04:00
/* Only wake if it is going to be searching. */
if ( tmp )
wake_up_process ( md - > thread ) ;
2005-06-04 01:31:02 +04:00
return count ;
}
static ssize_t w1_master_attribute_show_search ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
2005-08-11 17:27:49 +04:00
struct w1_master * md = dev_to_w1_master ( dev ) ;
2005-06-04 01:31:02 +04:00
ssize_t count ;
2006-04-03 12:04:27 +04:00
mutex_lock ( & md - > mutex ) ;
2005-06-04 01:31:02 +04:00
count = sprintf ( buf , " %d \n " , md - > search_count ) ;
2006-04-03 12:04:27 +04:00
mutex_unlock ( & md - > mutex ) ;
2005-06-04 01:31:02 +04:00
return count ;
}
2008-10-16 09:04:42 +04:00
static ssize_t w1_master_attribute_store_pullup ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
{
long tmp ;
struct w1_master * md = dev_to_w1_master ( dev ) ;
2013-09-12 01:26:03 +04:00
int ret ;
2008-10-16 09:04:42 +04:00
2013-09-12 01:26:03 +04:00
ret = kstrtol ( buf , 0 , & tmp ) ;
if ( ret )
return ret ;
2008-10-16 09:04:42 +04:00
mutex_lock ( & md - > mutex ) ;
md - > enable_pullup = tmp ;
mutex_unlock ( & md - > mutex ) ;
return count ;
}
static ssize_t w1_master_attribute_show_pullup ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
struct w1_master * md = dev_to_w1_master ( dev ) ;
ssize_t count ;
mutex_lock ( & md - > mutex ) ;
count = sprintf ( buf , " %d \n " , md - > enable_pullup ) ;
mutex_unlock ( & md - > mutex ) ;
return count ;
}
2005-05-17 14:44:04 +04:00
static ssize_t w1_master_attribute_show_pointer ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2005-08-11 17:27:49 +04:00
struct w1_master * md = dev_to_w1_master ( dev ) ;
2005-04-17 02:20:36 +04:00
ssize_t count ;
2005-05-20 22:33:25 +04:00
2006-04-03 12:04:27 +04:00
mutex_lock ( & md - > mutex ) ;
2005-04-17 02:20:36 +04:00
count = sprintf ( buf , " 0x%p \n " , md - > bus_master ) ;
2006-04-03 12:04:27 +04:00
mutex_unlock ( & md - > mutex ) ;
2005-04-17 02:20:36 +04:00
return count ;
}
2005-05-17 14:44:04 +04:00
static ssize_t w1_master_attribute_show_timeout ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
ssize_t count ;
count = sprintf ( buf , " %d \n " , w1_timeout ) ;
return count ;
}
2014-01-16 08:29:15 +04:00
static ssize_t w1_master_attribute_store_max_slave_count ( struct device * dev ,
struct device_attribute * attr , const char * buf , size_t count )
{
2014-02-12 01:07:55 +04:00
int tmp ;
2014-01-16 08:29:15 +04:00
struct w1_master * md = dev_to_w1_master ( dev ) ;
2014-02-12 01:07:55 +04:00
if ( kstrtoint ( buf , 0 , & tmp ) = = - EINVAL | | tmp < 1 )
2014-01-16 08:29:15 +04:00
return - EINVAL ;
mutex_lock ( & md - > mutex ) ;
md - > max_slave_count = tmp ;
/* allow each time the max_slave_count is updated */
clear_bit ( W1_WARN_MAX_COUNT , & md - > flags ) ;
mutex_unlock ( & md - > mutex ) ;
return count ;
}
2005-05-17 14:44:04 +04:00
static ssize_t w1_master_attribute_show_max_slave_count ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2005-08-11 17:27:49 +04:00
struct w1_master * md = dev_to_w1_master ( dev ) ;
2005-04-17 02:20:36 +04:00
ssize_t count ;
2005-05-20 22:33:25 +04:00
2006-04-03 12:04:27 +04:00
mutex_lock ( & md - > mutex ) ;
2005-04-17 02:20:36 +04:00
count = sprintf ( buf , " %d \n " , md - > max_slave_count ) ;
2006-04-03 12:04:27 +04:00
mutex_unlock ( & md - > mutex ) ;
2005-04-17 02:20:36 +04:00
return count ;
}
2005-05-17 14:44:04 +04:00
static ssize_t w1_master_attribute_show_attempts ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2005-08-11 17:27:49 +04:00
struct w1_master * md = dev_to_w1_master ( dev ) ;
2005-04-17 02:20:36 +04:00
ssize_t count ;
2005-05-20 22:33:25 +04:00
2006-04-03 12:04:27 +04:00
mutex_lock ( & md - > mutex ) ;
2005-04-17 02:20:36 +04:00
count = sprintf ( buf , " %lu \n " , md - > attempts ) ;
2006-04-03 12:04:27 +04:00
mutex_unlock ( & md - > mutex ) ;
2005-04-17 02:20:36 +04:00
return count ;
}
2005-05-17 14:44:04 +04:00
static ssize_t w1_master_attribute_show_slave_count ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2005-08-11 17:27:49 +04:00
struct w1_master * md = dev_to_w1_master ( dev ) ;
2005-04-17 02:20:36 +04:00
ssize_t count ;
2005-05-20 22:33:25 +04:00
2006-04-03 12:04:27 +04:00
mutex_lock ( & md - > mutex ) ;
2005-04-17 02:20:36 +04:00
count = sprintf ( buf , " %d \n " , md - > slave_count ) ;
2006-04-03 12:04:27 +04:00
mutex_unlock ( & md - > mutex ) ;
2005-04-17 02:20:36 +04:00
return count ;
}
2008-10-16 09:04:43 +04:00
static ssize_t w1_master_attribute_show_slaves ( struct device * dev ,
struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2005-08-11 17:27:49 +04:00
struct w1_master * md = dev_to_w1_master ( dev ) ;
2005-04-17 02:20:36 +04:00
int c = PAGE_SIZE ;
2014-01-16 08:29:18 +04:00
struct list_head * ent , * n ;
struct w1_slave * sl = NULL ;
2005-04-17 02:20:36 +04:00
2014-01-16 08:29:18 +04:00
mutex_lock ( & md - > list_mutex ) ;
2005-04-17 02:20:36 +04:00
2014-01-16 08:29:18 +04:00
list_for_each_safe ( ent , n , & md - > slist ) {
sl = list_entry ( ent , struct w1_slave , w1_slave_entry ) ;
2005-04-17 02:20:36 +04:00
2014-01-16 08:29:18 +04:00
c - = snprintf ( buf + PAGE_SIZE - c , c , " %s \n " , sl - > name ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-16 08:29:18 +04:00
if ( ! sl )
c - = snprintf ( buf + PAGE_SIZE - c , c , " not found. \n " ) ;
2005-04-17 02:20:36 +04:00
2014-01-16 08:29:18 +04:00
mutex_unlock ( & md - > list_mutex ) ;
2005-04-17 02:20:36 +04:00
return PAGE_SIZE - c ;
}
2008-10-16 09:04:43 +04:00
static ssize_t w1_master_attribute_show_add ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
int c = PAGE_SIZE ;
c - = snprintf ( buf + PAGE_SIZE - c , c ,
" write device id xx-xxxxxxxxxxxx to add slave \n " ) ;
return PAGE_SIZE - c ;
}
static int w1_atoreg_num ( struct device * dev , const char * buf , size_t count ,
struct w1_reg_num * rn )
{
unsigned int family ;
unsigned long long id ;
int i ;
u64 rn64_le ;
/* The CRC value isn't read from the user because the sysfs directory
* doesn ' t include it and most messages from the bus search don ' t
* print it either . It would be unreasonable for the user to then
* provide it .
*/
const char * error_msg = " bad slave string format, expecting "
" ff-dddddddddddd \n " ;
if ( buf [ 2 ] ! = ' - ' ) {
dev_err ( dev , " %s " , error_msg ) ;
return - EINVAL ;
}
i = sscanf ( buf , " %02x-%012llx " , & family , & id ) ;
if ( i ! = 2 ) {
dev_err ( dev , " %s " , error_msg ) ;
return - EINVAL ;
}
rn - > family = family ;
rn - > id = id ;
rn64_le = cpu_to_le64 ( * ( u64 * ) rn ) ;
rn - > crc = w1_calc_crc8 ( ( u8 * ) & rn64_le , 7 ) ;
#if 0
dev_info ( dev , " With CRC device is %02x.%012llx.%02x. \n " ,
rn - > family , ( unsigned long long ) rn - > id , rn - > crc ) ;
# endif
return 0 ;
}
/* Searches the slaves in the w1_master and returns a pointer or NULL.
2014-01-16 08:29:18 +04:00
* Note : must not hold list_mutex
2008-10-16 09:04:43 +04:00
*/
2014-01-16 08:29:17 +04:00
struct w1_slave * w1_slave_search_device ( struct w1_master * dev ,
2008-10-16 09:04:43 +04:00
struct w1_reg_num * rn )
{
struct w1_slave * sl ;
2014-01-16 08:29:18 +04:00
mutex_lock ( & dev - > list_mutex ) ;
2008-10-16 09:04:43 +04:00
list_for_each_entry ( sl , & dev - > slist , w1_slave_entry ) {
if ( sl - > reg_num . family = = rn - > family & &
sl - > reg_num . id = = rn - > id & &
sl - > reg_num . crc = = rn - > crc ) {
2014-01-16 08:29:18 +04:00
mutex_unlock ( & dev - > list_mutex ) ;
2008-10-16 09:04:43 +04:00
return sl ;
}
}
2014-01-16 08:29:18 +04:00
mutex_unlock ( & dev - > list_mutex ) ;
2008-10-16 09:04:43 +04:00
return NULL ;
}
static ssize_t w1_master_attribute_store_add ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
{
struct w1_master * md = dev_to_w1_master ( dev ) ;
struct w1_reg_num rn ;
struct w1_slave * sl ;
ssize_t result = count ;
if ( w1_atoreg_num ( dev , buf , count , & rn ) )
return - EINVAL ;
mutex_lock ( & md - > mutex ) ;
sl = w1_slave_search_device ( md , & rn ) ;
/* It would be nice to do a targeted search one the one-wire bus
* for the new device to see if it is out there or not . But the
* current search doesn ' t support that .
*/
if ( sl ) {
dev_info ( dev , " Device %s already exists \n " , sl - > name ) ;
result = - EINVAL ;
} else {
w1_attach_slave_device ( md , & rn ) ;
}
mutex_unlock ( & md - > mutex ) ;
return result ;
}
static ssize_t w1_master_attribute_show_remove ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
int c = PAGE_SIZE ;
c - = snprintf ( buf + PAGE_SIZE - c , c ,
" write device id xx-xxxxxxxxxxxx to remove slave \n " ) ;
return PAGE_SIZE - c ;
}
static ssize_t w1_master_attribute_store_remove ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
{
struct w1_master * md = dev_to_w1_master ( dev ) ;
struct w1_reg_num rn ;
struct w1_slave * sl ;
ssize_t result = count ;
if ( w1_atoreg_num ( dev , buf , count , & rn ) )
return - EINVAL ;
mutex_lock ( & md - > mutex ) ;
sl = w1_slave_search_device ( md , & rn ) ;
if ( sl ) {
2014-01-16 08:29:18 +04:00
result = w1_slave_detach ( sl ) ;
/* refcnt 0 means it was detached in the call */
if ( result = = 0 )
result = count ;
2008-10-16 09:04:43 +04:00
} else {
dev_info ( dev , " Device %02x-%012llx doesn't exists \n " , rn . family ,
( unsigned long long ) rn . id ) ;
result = - EINVAL ;
}
mutex_unlock ( & md - > mutex ) ;
return result ;
}
2005-05-20 22:33:25 +04:00
# define W1_MASTER_ATTR_RO(_name, _mode) \
struct device_attribute w1_master_attribute_ # # _name = \
__ATTR ( w1_master_ # # _name , _mode , \
w1_master_attribute_show_ # # _name , NULL )
2005-06-04 01:31:02 +04:00
# define W1_MASTER_ATTR_RW(_name, _mode) \
struct device_attribute w1_master_attribute_ # # _name = \
__ATTR ( w1_master_ # # _name , _mode , \
w1_master_attribute_show_ # # _name , \
w1_master_attribute_store_ # # _name )
2005-05-20 22:33:25 +04:00
static W1_MASTER_ATTR_RO ( name , S_IRUGO ) ;
static W1_MASTER_ATTR_RO ( slaves , S_IRUGO ) ;
static W1_MASTER_ATTR_RO ( slave_count , S_IRUGO ) ;
2014-01-16 08:29:15 +04:00
static W1_MASTER_ATTR_RW ( max_slave_count , S_IRUGO | S_IWUSR | S_IWGRP ) ;
2005-05-20 22:33:25 +04:00
static W1_MASTER_ATTR_RO ( attempts , S_IRUGO ) ;
static W1_MASTER_ATTR_RO ( timeout , S_IRUGO ) ;
static W1_MASTER_ATTR_RO ( pointer , S_IRUGO ) ;
2010-10-28 02:34:49 +04:00
static W1_MASTER_ATTR_RW ( search , S_IRUGO | S_IWUSR | S_IWGRP ) ;
static W1_MASTER_ATTR_RW ( pullup , S_IRUGO | S_IWUSR | S_IWGRP ) ;
static W1_MASTER_ATTR_RW ( add , S_IRUGO | S_IWUSR | S_IWGRP ) ;
static W1_MASTER_ATTR_RW ( remove , S_IRUGO | S_IWUSR | S_IWGRP ) ;
2005-05-20 22:33:25 +04:00
static struct attribute * w1_master_default_attrs [ ] = {
& w1_master_attribute_name . attr ,
& w1_master_attribute_slaves . attr ,
& w1_master_attribute_slave_count . attr ,
& w1_master_attribute_max_slave_count . attr ,
& w1_master_attribute_attempts . attr ,
& w1_master_attribute_timeout . attr ,
& w1_master_attribute_pointer . attr ,
2005-06-04 01:31:02 +04:00
& w1_master_attribute_search . attr ,
2008-10-16 09:04:42 +04:00
& w1_master_attribute_pullup . attr ,
2008-10-16 09:04:43 +04:00
& w1_master_attribute_add . attr ,
& w1_master_attribute_remove . attr ,
2005-05-20 22:33:25 +04:00
NULL
2005-04-17 02:20:36 +04:00
} ;
2005-05-20 22:33:25 +04:00
static struct attribute_group w1_master_defattr_group = {
. attrs = w1_master_default_attrs ,
2005-04-17 02:20:36 +04:00
} ;
2005-05-20 22:33:25 +04:00
int w1_create_master_attributes ( struct w1_master * master )
{
return sysfs_create_group ( & master - > dev . kobj , & w1_master_defattr_group ) ;
}
2008-10-16 09:04:38 +04:00
void w1_destroy_master_attributes ( struct w1_master * master )
2005-05-20 22:33:25 +04:00
{
sysfs_remove_group ( & master - > dev . kobj , & w1_master_defattr_group ) ;
}
2007-08-14 17:15:12 +04:00
static int w1_uevent ( struct device * dev , struct kobj_uevent_env * env )
2005-08-11 13:20:07 +04:00
{
struct w1_master * md = NULL ;
struct w1_slave * sl = NULL ;
char * event_owner , * name ;
2012-05-19 07:31:54 +04:00
int err = 0 ;
2005-08-11 13:20:07 +04:00
if ( dev - > driver = = & w1_master_driver ) {
md = container_of ( dev , struct w1_master , dev ) ;
event_owner = " master " ;
name = md - > name ;
} else if ( dev - > driver = = & w1_slave_driver ) {
sl = container_of ( dev , struct w1_slave , dev ) ;
event_owner = " slave " ;
name = sl - > name ;
} else {
2005-11-16 11:00:00 +03:00
dev_dbg ( dev , " Unknown event. \n " ) ;
2005-08-11 13:20:07 +04:00
return - EINVAL ;
}
2006-05-15 08:43:50 +04:00
dev_dbg ( dev , " Hotplug event for %s %s, bus_id=%s. \n " ,
2009-01-06 21:44:34 +03:00
event_owner , name , dev_name ( dev ) ) ;
2005-08-11 13:20:07 +04:00
if ( dev - > driver ! = & w1_slave_driver | | ! sl )
2012-05-19 07:31:54 +04:00
goto end ;
2005-08-11 13:20:07 +04:00
2007-08-14 17:15:12 +04:00
err = add_uevent_var ( env , " W1_FID=%02X " , sl - > reg_num . family ) ;
2005-08-11 13:20:07 +04:00
if ( err )
2012-05-19 07:31:54 +04:00
goto end ;
2005-08-11 13:20:07 +04:00
2007-08-14 17:15:12 +04:00
err = add_uevent_var ( env , " W1_SLAVE_ID=%024LX " ,
( unsigned long long ) sl - > reg_num . id ) ;
2012-05-19 07:31:54 +04:00
end :
return err ;
}
2005-08-11 13:20:07 +04:00
2014-04-16 10:21:21 +04:00
static int w1_family_notify ( unsigned long action , struct w1_slave * sl )
2013-08-22 00:24:32 +04:00
{
2013-08-22 02:44:55 +04:00
struct w1_family_ops * fops ;
2013-08-22 00:24:32 +04:00
int err ;
2013-08-22 02:44:55 +04:00
fops = sl - > family - > fops ;
2013-08-22 00:24:32 +04:00
2013-10-06 23:13:35 +04:00
if ( ! fops )
return 0 ;
2013-08-22 00:24:32 +04:00
switch ( action ) {
case BUS_NOTIFY_ADD_DEVICE :
/* if the family driver needs to initialize something... */
2013-08-22 02:44:55 +04:00
if ( fops - > add_slave ) {
err = fops - > add_slave ( sl ) ;
if ( err < 0 ) {
dev_err ( & sl - > dev ,
" add_slave() call failed. err=%d \n " ,
err ) ;
return err ;
}
}
if ( fops - > groups ) {
err = sysfs_create_groups ( & sl - > dev . kobj , fops - > groups ) ;
if ( err ) {
dev_err ( & sl - > dev ,
" sysfs group creation failed. err=%d \n " ,
err ) ;
return err ;
}
2013-08-22 00:24:32 +04:00
}
break ;
case BUS_NOTIFY_DEL_DEVICE :
2013-08-22 02:44:55 +04:00
if ( fops - > remove_slave )
2013-08-22 00:24:32 +04:00
sl - > family - > fops - > remove_slave ( sl ) ;
2013-08-22 02:44:55 +04:00
if ( fops - > groups )
sysfs_remove_groups ( & sl - > dev . kobj , fops - > groups ) ;
2013-08-22 00:24:32 +04:00
break ;
}
return 0 ;
}
2005-04-17 02:20:36 +04:00
static int __w1_attach_slave_device ( struct w1_slave * sl )
{
int err ;
sl - > dev . parent = & sl - > master - > dev ;
2005-08-11 13:20:07 +04:00
sl - > dev . driver = & w1_slave_driver ;
2005-04-17 02:20:36 +04:00
sl - > dev . bus = & w1_bus_type ;
sl - > dev . release = & w1_slave_release ;
2013-08-22 00:24:33 +04:00
sl - > dev . groups = w1_slave_groups ;
2005-04-17 02:20:36 +04:00
2009-01-06 21:44:34 +03:00
dev_set_name ( & sl - > dev , " %02x-%012llx " ,
2005-06-04 01:30:43 +04:00
( unsigned int ) sl - > reg_num . family ,
( unsigned long long ) sl - > reg_num . id ) ;
snprintf ( & sl - > name [ 0 ] , sizeof ( sl - > name ) ,
" %02x-%012llx " ,
( unsigned int ) sl - > reg_num . family ,
( unsigned long long ) sl - > reg_num . id ) ;
2005-04-17 02:20:36 +04:00
2006-05-15 08:43:50 +04:00
dev_dbg ( & sl - > dev , " %s: registering %s as %p. \n " , __func__ ,
2009-01-06 21:44:34 +03:00
dev_name ( & sl - > dev ) , sl ) ;
2005-04-17 02:20:36 +04:00
2014-04-16 10:21:21 +04:00
/* suppress for w1_family_notify before sending KOBJ_ADD */
dev_set_uevent_suppress ( & sl - > dev , true ) ;
2005-04-17 02:20:36 +04:00
err = device_register ( & sl - > dev ) ;
if ( err < 0 ) {
dev_err ( & sl - > dev ,
2005-06-04 01:30:43 +04:00
" Device registration [%s] failed. err=%d \n " ,
2009-01-06 21:44:34 +03:00
dev_name ( & sl - > dev ) , err ) ;
2005-04-17 02:20:36 +04:00
return err ;
}
2014-04-16 10:21:21 +04:00
w1_family_notify ( BUS_NOTIFY_ADD_DEVICE , sl ) ;
2005-04-17 02:20:36 +04:00
2013-08-22 00:24:32 +04:00
dev_set_uevent_suppress ( & sl - > dev , false ) ;
kobject_uevent ( & sl - > dev . kobj , KOBJ_ADD ) ;
2005-04-17 02:20:36 +04:00
2014-01-16 08:29:18 +04:00
mutex_lock ( & sl - > master - > list_mutex ) ;
2005-04-17 02:20:36 +04:00
list_add_tail ( & sl - > w1_slave_entry , & sl - > master - > slist ) ;
2014-01-16 08:29:18 +04:00
mutex_unlock ( & sl - > master - > list_mutex ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2014-01-16 08:29:17 +04:00
int w1_attach_slave_device ( struct w1_master * dev , struct w1_reg_num * rn )
2005-04-17 02:20:36 +04:00
{
struct w1_slave * sl ;
struct w1_family * f ;
int err ;
struct w1_netlink_msg msg ;
some kmalloc/memset ->kzalloc (tree wide)
Transform some calls to kmalloc/memset to a single kzalloc (or kcalloc).
Here is a short excerpt of the semantic patch performing
this transformation:
@@
type T2;
expression x;
identifier f,fld;
expression E;
expression E1,E2;
expression e1,e2,e3,y;
statement S;
@@
x =
- kmalloc
+ kzalloc
(E1,E2)
... when != \(x->fld=E;\|y=f(...,x,...);\|f(...,x,...);\|x=E;\|while(...) S\|for(e1;e2;e3) S\)
- memset((T2)x,0,E1);
@@
expression E1,E2,E3;
@@
- kzalloc(E1 * E2,E3)
+ kcalloc(E1,E2,E3)
[akpm@linux-foundation.org: get kcalloc args the right way around]
Signed-off-by: Yoann Padioleau <padator@wanadoo.fr>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Acked-by: Russell King <rmk@arm.linux.org.uk>
Cc: Bryan Wu <bryan.wu@analog.com>
Acked-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Dave Airlie <airlied@linux.ie>
Acked-by: Roland Dreier <rolandd@cisco.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Acked-by: Dmitry Torokhov <dtor@mail.ru>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Acked-by: Pierre Ossman <drzeus-list@drzeus.cx>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: "David S. Miller" <davem@davemloft.net>
Acked-by: Greg KH <greg@kroah.com>
Cc: James Bottomley <James.Bottomley@steeleye.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-19 12:49:03 +04:00
sl = kzalloc ( sizeof ( struct w1_slave ) , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! sl ) {
dev_err ( & dev - > dev ,
" %s: failed to allocate new slave device. \n " ,
__func__ ) ;
return - ENOMEM ;
}
sl - > owner = THIS_MODULE ;
sl - > master = dev ;
2013-11-13 03:11:42 +04:00
set_bit ( W1_SLAVE_ACTIVE , & sl - > flags ) ;
2005-04-17 02:20:36 +04:00
2006-03-23 19:11:58 +03:00
memset ( & msg , 0 , sizeof ( msg ) ) ;
2005-04-17 02:20:36 +04:00
memcpy ( & sl - > reg_num , rn , sizeof ( sl - > reg_num ) ) ;
2014-01-16 08:29:18 +04:00
atomic_set ( & sl - > refcnt , 1 ) ;
atomic_inc ( & sl - > master - > refcnt ) ;
2005-04-17 02:20:36 +04:00
2013-10-06 23:13:40 +04:00
/* slave modules need to be loaded in a context with unlocked mutex */
mutex_unlock ( & dev - > mutex ) ;
2014-11-19 06:04:20 +03:00
request_module ( " w1-family-0x%02x " , rn - > family ) ;
2013-10-06 23:13:40 +04:00
mutex_lock ( & dev - > mutex ) ;
2013-05-26 22:06:50 +04:00
2005-04-17 02:20:36 +04:00
spin_lock ( & w1_flock ) ;
f = w1_family_registered ( rn - > family ) ;
if ( ! f ) {
2005-06-04 01:31:26 +04:00
f = & w1_default_family ;
2005-04-17 02:20:36 +04:00
dev_info ( & dev - > dev , " Family %x for %02x.%012llx.%02x is not registered. \n " ,
rn - > family , rn - > family ,
( unsigned long long ) rn - > id , rn - > crc ) ;
}
__w1_family_get ( f ) ;
spin_unlock ( & w1_flock ) ;
sl - > family = f ;
err = __w1_attach_slave_device ( sl ) ;
if ( err < 0 ) {
dev_err ( & dev - > dev , " %s: Attaching %s failed. \n " , __func__ ,
sl - > name ) ;
w1_family_put ( sl - > family ) ;
kfree ( sl ) ;
return err ;
}
sl - > ttl = dev - > slave_ttl ;
dev - > slave_count + + ;
2006-03-23 19:11:58 +03:00
memcpy ( msg . id . id , rn , sizeof ( msg . id ) ) ;
2005-04-17 02:20:36 +04:00
msg . type = W1_SLAVE_ADD ;
w1_netlink_send ( dev , & msg ) ;
return 0 ;
}
2014-01-16 08:29:18 +04:00
int w1_unref_slave ( struct w1_slave * sl )
2005-04-17 02:20:36 +04:00
{
2014-01-16 08:29:18 +04:00
struct w1_master * dev = sl - > master ;
int refcnt ;
mutex_lock ( & dev - > list_mutex ) ;
refcnt = atomic_sub_return ( 1 , & sl - > refcnt ) ;
if ( refcnt = = 0 ) {
struct w1_netlink_msg msg ;
dev_dbg ( & sl - > dev , " %s: detaching %s [%p]. \n " , __func__ ,
sl - > name , sl ) ;
list_del ( & sl - > w1_slave_entry ) ;
memset ( & msg , 0 , sizeof ( msg ) ) ;
memcpy ( msg . id . id , & sl - > reg_num , sizeof ( msg . id ) ) ;
msg . type = W1_SLAVE_REMOVE ;
w1_netlink_send ( sl - > master , & msg ) ;
2014-04-16 10:21:21 +04:00
w1_family_notify ( BUS_NOTIFY_DEL_DEVICE , sl ) ;
2014-01-16 08:29:18 +04:00
device_unregister ( & sl - > dev ) ;
# ifdef DEBUG
memset ( sl , 0 , sizeof ( * sl ) ) ;
# endif
kfree ( sl ) ;
}
atomic_dec ( & dev - > refcnt ) ;
mutex_unlock ( & dev - > list_mutex ) ;
return refcnt ;
}
2005-04-17 02:20:36 +04:00
2014-01-16 08:29:18 +04:00
int w1_slave_detach ( struct w1_slave * sl )
{
/* Only detach a slave once as it decreases the refcnt each time. */
int destroy_now ;
mutex_lock ( & sl - > master - > list_mutex ) ;
destroy_now = ! test_bit ( W1_SLAVE_DETACH , & sl - > flags ) ;
set_bit ( W1_SLAVE_DETACH , & sl - > flags ) ;
mutex_unlock ( & sl - > master - > list_mutex ) ;
if ( destroy_now )
destroy_now = ! w1_unref_slave ( sl ) ;
return destroy_now ? 0 : - EBUSY ;
2005-04-17 02:20:36 +04:00
}
2006-03-23 19:11:58 +03:00
struct w1_master * w1_search_master_id ( u32 id )
{
struct w1_master * dev ;
int found = 0 ;
2006-04-03 12:04:27 +04:00
mutex_lock ( & w1_mlock ) ;
2006-03-23 19:11:58 +03:00
list_for_each_entry ( dev , & w1_masters , w1_master_entry ) {
if ( dev - > id = = id ) {
found = 1 ;
atomic_inc ( & dev - > refcnt ) ;
break ;
}
}
2006-04-03 12:04:27 +04:00
mutex_unlock ( & w1_mlock ) ;
2006-03-23 19:11:58 +03:00
return ( found ) ? dev : NULL ;
}
struct w1_slave * w1_search_slave ( struct w1_reg_num * id )
{
struct w1_master * dev ;
struct w1_slave * sl = NULL ;
int found = 0 ;
2006-04-03 12:04:27 +04:00
mutex_lock ( & w1_mlock ) ;
2006-03-23 19:11:58 +03:00
list_for_each_entry ( dev , & w1_masters , w1_master_entry ) {
2014-01-16 08:29:18 +04:00
mutex_lock ( & dev - > list_mutex ) ;
2006-03-23 19:11:58 +03:00
list_for_each_entry ( sl , & dev - > slist , w1_slave_entry ) {
if ( sl - > reg_num . family = = id - > family & &
sl - > reg_num . id = = id - > id & &
sl - > reg_num . crc = = id - > crc ) {
found = 1 ;
atomic_inc ( & dev - > refcnt ) ;
atomic_inc ( & sl - > refcnt ) ;
break ;
}
}
2014-01-16 08:29:18 +04:00
mutex_unlock ( & dev - > list_mutex ) ;
2006-03-23 19:11:58 +03:00
if ( found )
break ;
}
2006-04-03 12:04:27 +04:00
mutex_unlock ( & w1_mlock ) ;
2006-03-23 19:11:58 +03:00
return ( found ) ? sl : NULL ;
}
2008-10-16 09:04:38 +04:00
void w1_reconnect_slaves ( struct w1_family * f , int attach )
2005-06-04 01:29:25 +04:00
{
2008-10-16 09:04:38 +04:00
struct w1_slave * sl , * sln ;
2005-06-04 01:29:25 +04:00
struct w1_master * dev ;
2006-04-03 12:04:27 +04:00
mutex_lock ( & w1_mlock ) ;
2005-06-04 01:29:25 +04:00
list_for_each_entry ( dev , & w1_masters , w1_master_entry ) {
2008-10-16 09:04:38 +04:00
dev_dbg ( & dev - > dev , " Reconnecting slaves in device %s "
" for family %02x. \n " , dev - > name , f - > fid ) ;
mutex_lock ( & dev - > mutex ) ;
2014-01-16 08:29:18 +04:00
mutex_lock ( & dev - > list_mutex ) ;
2008-10-16 09:04:38 +04:00
list_for_each_entry_safe ( sl , sln , & dev - > slist , w1_slave_entry ) {
/* If it is a new family, slaves with the default
* family driver and are that family will be
* connected . If the family is going away , devices
* matching that family are reconneced .
*/
if ( ( attach & & sl - > family - > fid = = W1_FAMILY_DEFAULT
& & sl - > reg_num . family = = f - > fid ) | |
( ! attach & & sl - > family - > fid = = f - > fid ) ) {
struct w1_reg_num rn ;
2014-01-16 08:29:18 +04:00
mutex_unlock ( & dev - > list_mutex ) ;
2008-10-16 09:04:38 +04:00
memcpy ( & rn , & sl - > reg_num , sizeof ( rn ) ) ;
2014-01-16 08:29:18 +04:00
/* If it was already in use let the automatic
* scan pick it up again later .
*/
if ( ! w1_slave_detach ( sl ) )
w1_attach_slave_device ( dev , & rn ) ;
mutex_lock ( & dev - > list_mutex ) ;
2008-10-16 09:04:38 +04:00
}
}
dev_dbg ( & dev - > dev , " Reconnecting slaves in device %s "
" has been finished. \n " , dev - > name ) ;
2014-01-16 08:29:18 +04:00
mutex_unlock ( & dev - > list_mutex ) ;
2008-10-16 09:04:38 +04:00
mutex_unlock ( & dev - > mutex ) ;
2005-06-04 01:29:25 +04:00
}
2006-04-03 12:04:27 +04:00
mutex_unlock ( & w1_mlock ) ;
2005-06-04 01:29:25 +04:00
}
2011-05-27 03:26:03 +04:00
void w1_slave_found ( struct w1_master * dev , u64 rn )
2005-04-17 02:20:36 +04:00
{
struct w1_slave * sl ;
struct w1_reg_num * tmp ;
2005-06-30 22:52:38 +04:00
u64 rn_le = cpu_to_le64 ( rn ) ;
2005-04-17 02:20:36 +04:00
2008-10-16 09:04:38 +04:00
atomic_inc ( & dev - > refcnt ) ;
2005-05-20 22:33:25 +04:00
2005-04-17 02:20:36 +04:00
tmp = ( struct w1_reg_num * ) & rn ;
2008-10-16 09:04:44 +04:00
sl = w1_slave_search_device ( dev , tmp ) ;
if ( sl ) {
2013-11-13 03:11:42 +04:00
set_bit ( W1_SLAVE_ACTIVE , & sl - > flags ) ;
2008-10-16 09:04:44 +04:00
} else {
if ( rn & & tmp - > crc = = w1_calc_crc8 ( ( u8 * ) & rn_le , 7 ) )
w1_attach_slave_device ( dev , tmp ) ;
2005-04-17 02:20:36 +04:00
}
2005-05-20 22:33:25 +04:00
2005-04-17 02:20:36 +04:00
atomic_dec ( & dev - > refcnt ) ;
}
2005-06-04 01:30:43 +04:00
/**
2014-01-16 08:29:25 +04:00
* w1_search ( ) - Performs a ROM Search & registers any devices found .
* @ dev : The master device to search
* @ search_type : W1_SEARCH to search all devices , or W1_ALARM_SEARCH
* to return only devices in the alarmed state
* @ cb : Function to call when a device is found
*
2005-06-04 01:30:43 +04:00
* The 1 - wire search is a simple binary tree search .
* For each bit of the address , we read two bits and write one bit .
* The bit written will put to sleep all devies that don ' t match that bit .
* When the two reads differ , the direction choice is obvious .
* When both bits are 0 , we must choose a path to take .
* When we can scan all 64 bits without having to choose a path , we are done .
*
* See " Application note 187 1-wire search algorithm " at www . maxim - ic . com
*
*/
2006-03-23 19:11:58 +03:00
void w1_search ( struct w1_master * dev , u8 search_type , w1_slave_found_callback cb )
2005-04-17 02:20:36 +04:00
{
2005-06-04 01:30:43 +04:00
u64 last_rn , rn , tmp64 ;
int i , slave_count = 0 ;
int last_zero , last_device ;
int search_bit , desc_bit ;
u8 triplet_ret = 0 ;
2005-04-17 02:20:36 +04:00
2005-06-04 01:30:43 +04:00
search_bit = 0 ;
2014-01-16 08:29:16 +04:00
rn = dev - > search_id ;
last_rn = 0 ;
2005-06-04 01:30:43 +04:00
last_device = 0 ;
last_zero = - 1 ;
2005-04-17 02:20:36 +04:00
desc_bit = 64 ;
2005-06-04 01:30:43 +04:00
while ( ! last_device & & ( slave_count + + < dev - > max_slave_count ) ) {
last_rn = rn ;
2005-04-17 02:20:36 +04:00
rn = 0 ;
/*
* Reset bus and all 1 - wire device state machines
* so they can respond to our requests .
*
* Return 0 - device ( s ) present , 1 - no devices present .
*/
2012-05-18 09:59:52 +04:00
mutex_lock ( & dev - > bus_mutex ) ;
2005-04-17 02:20:36 +04:00
if ( w1_reset_bus ( dev ) ) {
2012-05-18 09:59:52 +04:00
mutex_unlock ( & dev - > bus_mutex ) ;
2005-08-12 22:46:22 +04:00
dev_dbg ( & dev - > dev , " No devices present on the wire. \n " ) ;
2005-04-17 02:20:36 +04:00
break ;
}
2011-12-10 05:36:11 +04:00
/* Do fast search on single slave bus */
if ( dev - > max_slave_count = = 1 ) {
2012-05-18 09:59:52 +04:00
int rv ;
2011-12-10 05:36:11 +04:00
w1_write_8 ( dev , W1_READ_ROM ) ;
2012-05-18 09:59:52 +04:00
rv = w1_read_block ( dev , ( u8 * ) & rn , 8 ) ;
mutex_unlock ( & dev - > bus_mutex ) ;
2011-12-10 05:36:11 +04:00
2012-05-18 09:59:52 +04:00
if ( rv = = 8 & & rn )
2011-12-10 05:36:11 +04:00
cb ( dev , rn ) ;
break ;
}
2005-06-04 01:30:43 +04:00
/* Start the search */
2006-03-23 19:11:58 +03:00
w1_write_8 ( dev , search_type ) ;
2005-04-17 02:20:36 +04:00
for ( i = 0 ; i < 64 ; + + i ) {
2005-06-04 01:30:43 +04:00
/* Determine the direction/search bit */
if ( i = = desc_bit )
search_bit = 1 ; /* took the 0 path last time, so take the 1 path */
else if ( i > desc_bit )
search_bit = 0 ; /* take the 0 path on the next branch */
2005-04-17 02:20:36 +04:00
else
2005-06-04 01:30:43 +04:00
search_bit = ( ( last_rn > > i ) & 0x1 ) ;
2005-04-17 02:20:36 +04:00
2014-01-16 08:29:25 +04:00
/* Read two bits and write one bit */
2005-06-04 01:30:43 +04:00
triplet_ret = w1_triplet ( dev , search_bit ) ;
/* quit if no device responded */
if ( ( triplet_ret & 0x03 ) = = 0x03 )
break ;
2005-04-17 02:20:36 +04:00
2005-06-04 01:30:43 +04:00
/* If both directions were valid, and we took the 0 path... */
if ( triplet_ret = = 0 )
last_zero = i ;
2005-04-17 02:20:36 +04:00
2005-06-04 01:30:43 +04:00
/* extract the direction taken & update the device number */
tmp64 = ( triplet_ret > > 2 ) ;
rn | = ( tmp64 < < i ) ;
2008-10-16 09:04:39 +04:00
2014-01-16 08:29:13 +04:00
if ( test_bit ( W1_ABORT_SEARCH , & dev - > flags ) ) {
2012-05-18 09:59:52 +04:00
mutex_unlock ( & dev - > bus_mutex ) ;
2008-10-16 09:04:58 +04:00
dev_dbg ( & dev - > dev , " Abort w1_search \n " ) ;
2008-10-16 09:04:39 +04:00
return ;
}
2005-06-04 01:30:43 +04:00
}
2012-05-18 09:59:52 +04:00
mutex_unlock ( & dev - > bus_mutex ) ;
2005-05-20 22:33:25 +04:00
2005-06-04 01:30:43 +04:00
if ( ( triplet_ret & 0x03 ) ! = 0x03 ) {
2014-01-16 08:29:16 +04:00
if ( ( desc_bit = = last_zero ) | | ( last_zero < 0 ) ) {
2005-06-04 01:30:43 +04:00
last_device = 1 ;
2014-01-16 08:29:16 +04:00
dev - > search_id = 0 ;
} else {
dev - > search_id = rn ;
}
2005-06-04 01:30:43 +04:00
desc_bit = last_zero ;
2008-10-16 09:04:38 +04:00
cb ( dev , rn ) ;
2005-06-04 01:30:43 +04:00
}
2014-01-16 08:29:15 +04:00
if ( ! last_device & & slave_count = = dev - > max_slave_count & &
! test_bit ( W1_WARN_MAX_COUNT , & dev - > flags ) ) {
2014-01-16 08:29:16 +04:00
/* Only max_slave_count will be scanned in a search,
* but it will start where it left off next search
* until all ids are identified and then it will start
* over . A continued search will report the previous
* last id as the first id ( provided it is still on the
* bus ) .
*/
2014-01-16 08:29:15 +04:00
dev_info ( & dev - > dev , " %s: max_slave_count %d reached, "
2014-01-16 08:29:16 +04:00
" will continue next search. \n " , __func__ ,
2014-01-16 08:29:15 +04:00
dev - > max_slave_count ) ;
set_bit ( W1_WARN_MAX_COUNT , & dev - > flags ) ;
}
2005-04-17 02:20:36 +04:00
}
}
2011-05-27 03:26:03 +04:00
void w1_search_process_cb ( struct w1_master * dev , u8 search_type ,
w1_slave_found_callback cb )
2006-03-23 19:11:58 +03:00
{
struct w1_slave * sl , * sln ;
2014-01-16 08:29:18 +04:00
mutex_lock ( & dev - > list_mutex ) ;
2006-03-23 19:11:58 +03:00
list_for_each_entry ( sl , & dev - > slist , w1_slave_entry )
2013-11-13 03:11:42 +04:00
clear_bit ( W1_SLAVE_ACTIVE , & sl - > flags ) ;
2014-01-16 08:29:18 +04:00
mutex_unlock ( & dev - > list_mutex ) ;
2006-03-23 19:11:58 +03:00
2011-05-27 03:26:03 +04:00
w1_search_devices ( dev , search_type , cb ) ;
2006-03-23 19:11:58 +03:00
2014-01-16 08:29:18 +04:00
mutex_lock ( & dev - > list_mutex ) ;
2006-03-23 19:11:58 +03:00
list_for_each_entry_safe ( sl , sln , & dev - > slist , w1_slave_entry ) {
2014-01-16 08:29:18 +04:00
if ( ! test_bit ( W1_SLAVE_ACTIVE , & sl - > flags ) & & ! - - sl - > ttl ) {
mutex_unlock ( & dev - > list_mutex ) ;
2006-03-23 19:11:58 +03:00
w1_slave_detach ( sl ) ;
2014-01-16 08:29:18 +04:00
mutex_lock ( & dev - > list_mutex ) ;
}
2013-11-13 03:11:42 +04:00
else if ( test_bit ( W1_SLAVE_ACTIVE , & sl - > flags ) )
2006-03-23 19:11:58 +03:00
sl - > ttl = dev - > slave_ttl ;
}
2014-01-16 08:29:18 +04:00
mutex_unlock ( & dev - > list_mutex ) ;
2006-03-23 19:11:58 +03:00
if ( dev - > search_count > 0 )
dev - > search_count - - ;
}
2011-05-27 03:26:03 +04:00
static void w1_search_process ( struct w1_master * dev , u8 search_type )
{
w1_search_process_cb ( dev , search_type , w1_slave_found ) ;
}
2014-01-16 08:29:25 +04:00
/**
* w1_process_callbacks ( ) - execute each dev - > async_list callback entry
* @ dev : w1_master device
*
2014-05-07 01:26:04 +04:00
* The w1 master list_mutex must be held .
*
2014-01-16 08:29:25 +04:00
* Return : 1 if there were commands to executed 0 otherwise
*/
2014-01-16 08:29:18 +04:00
int w1_process_callbacks ( struct w1_master * dev )
{
int ret = 0 ;
struct w1_async_cmd * async_cmd , * async_n ;
/* The list can be added to in another thread, loop until it is empty */
while ( ! list_empty ( & dev - > async_list ) ) {
list_for_each_entry_safe ( async_cmd , async_n , & dev - > async_list ,
async_entry ) {
/* drop the lock, if it is a search it can take a long
* time */
mutex_unlock ( & dev - > list_mutex ) ;
async_cmd - > cb ( dev , async_cmd ) ;
ret = 1 ;
mutex_lock ( & dev - > list_mutex ) ;
}
}
return ret ;
}
2005-04-17 02:20:36 +04:00
int w1_process ( void * data )
{
struct w1_master * dev = ( struct w1_master * ) data ;
2008-10-16 09:04:41 +04:00
/* As long as w1_timeout is only set by a module parameter the sleep
* time can be calculated in jiffies once .
*/
const unsigned long jtime = msecs_to_jiffies ( w1_timeout * 1000 ) ;
2014-01-16 08:29:18 +04:00
/* remainder if it woke up early */
unsigned long jremain = 0 ;
2005-04-17 02:20:36 +04:00
2014-01-16 08:29:18 +04:00
for ( ; ; ) {
if ( ! jremain & & dev - > search_count ) {
2008-10-16 09:04:40 +04:00
mutex_lock ( & dev - > mutex ) ;
w1_search_process ( dev , W1_SEARCH ) ;
mutex_unlock ( & dev - > mutex ) ;
}
2014-01-16 08:29:18 +04:00
mutex_lock ( & dev - > list_mutex ) ;
/* Note, w1_process_callback drops the lock while processing,
* but locks it again before returning .
*/
if ( ! w1_process_callbacks ( dev ) & & jremain ) {
/* a wake up is either to stop the thread, process
* callbacks , or search , it isn ' t process callbacks , so
* schedule a search .
*/
jremain = 1 ;
}
2005-06-25 10:13:50 +04:00
try_to_freeze ( ) ;
2008-10-16 09:04:41 +04:00
__set_current_state ( TASK_INTERRUPTIBLE ) ;
2014-01-16 08:29:18 +04:00
/* hold list_mutex until after interruptible to prevent loosing
* the wakeup signal when async_cmd is added .
*/
mutex_unlock ( & dev - > list_mutex ) ;
2008-10-16 09:04:41 +04:00
if ( kthread_should_stop ( ) )
break ;
/* Only sleep when the search is active. */
2014-01-16 08:29:18 +04:00
if ( dev - > search_count ) {
if ( ! jremain )
jremain = jtime ;
jremain = schedule_timeout ( jremain ) ;
}
2008-10-16 09:04:41 +04:00
else
schedule ( ) ;
2005-04-17 02:20:36 +04:00
}
atomic_dec ( & dev - > refcnt ) ;
return 0 ;
}
2009-12-22 11:38:02 +03:00
static int __init w1_init ( void )
2005-04-17 02:20:36 +04:00
{
int retval ;
2014-06-19 04:52:00 +04:00
pr_info ( " Driver for 1-wire Dallas network protocol. \n " ) ;
2005-04-17 02:20:36 +04:00
2006-03-23 19:11:58 +03:00
w1_init_netlink ( ) ;
2005-04-17 02:20:36 +04:00
retval = bus_register ( & w1_bus_type ) ;
if ( retval ) {
2014-06-19 04:52:00 +04:00
pr_err ( " Failed to register bus. err=%d. \n " , retval ) ;
2005-04-17 02:20:36 +04:00
goto err_out_exit_init ;
}
2005-08-11 13:20:07 +04:00
retval = driver_register ( & w1_master_driver ) ;
2005-04-17 02:20:36 +04:00
if ( retval ) {
2014-06-19 04:52:00 +04:00
pr_err ( " Failed to register master driver. err=%d. \n " ,
2005-04-17 02:20:36 +04:00
retval ) ;
goto err_out_bus_unregister ;
}
2005-08-11 13:20:07 +04:00
retval = driver_register ( & w1_slave_driver ) ;
if ( retval ) {
2014-06-19 04:52:00 +04:00
pr_err ( " Failed to register slave driver. err=%d. \n " ,
2005-08-11 13:20:07 +04:00
retval ) ;
goto err_out_master_unregister ;
}
2005-04-17 02:20:36 +04:00
return 0 ;
2008-10-16 09:04:38 +04:00
#if 0
/* For undoing the slave register if there was a step after it. */
2005-08-11 13:20:07 +04:00
err_out_slave_unregister :
driver_unregister ( & w1_slave_driver ) ;
2008-10-16 09:04:38 +04:00
# endif
2005-08-11 13:20:07 +04:00
err_out_master_unregister :
driver_unregister ( & w1_master_driver ) ;
2005-04-17 02:20:36 +04:00
err_out_bus_unregister :
bus_unregister ( & w1_bus_type ) ;
err_out_exit_init :
return retval ;
}
2009-12-22 11:38:02 +03:00
static void __exit w1_fini ( void )
2005-04-17 02:20:36 +04:00
{
struct w1_master * dev ;
2008-10-16 09:04:38 +04:00
/* Set netlink removal messages and some cleanup */
2005-05-20 22:33:25 +04:00
list_for_each_entry ( dev , & w1_masters , w1_master_entry )
2005-04-17 02:20:36 +04:00
__w1_remove_master_device ( dev ) ;
2006-03-23 19:11:58 +03:00
w1_fini_netlink ( ) ;
2005-08-11 13:20:07 +04:00
driver_unregister ( & w1_slave_driver ) ;
driver_unregister ( & w1_master_driver ) ;
2005-04-17 02:20:36 +04:00
bus_unregister ( & w1_bus_type ) ;
}
module_init ( w1_init ) ;
module_exit ( w1_fini ) ;