On 23/02/07 22:29, Simon Arlott wrote: > When the device is polled for status there is a lot of useful status > information available that is ignored. This patch stores the device > info array when the status is polled and adds sysfs files to the usb > device to allow userspace to query it. Since the device updates its > status internally once a second the poll time is changed to this, and > round_jiffies_relative is used to avoid waking the cpu unnecessarily. I also have a patch that can call the ADSL start/stop function on the device via sysfs, but it's inherently unstable because requests to start when running or stop when stopped will blocking until the state is changed. redrum 3-2:1.0 # echo no >adsl_running Feb 23 22:35:28 redrum [ 8574.166565] ATM dev 0: ADSL line: down redrum 3-2:1.0 # echo yes >adsl_running Feb 23 22:35:34 redrum [ 8580.169400] ATM dev 0: ADSL line: initializing --- diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index c8b69bf..33d6a7e 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -171,6 +171,9 @@ struct cxacru_data { struct completion snd_done; }; +static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, + u8 *wdata, int wsize, u8 *rdata, int rsize); + /* Card info exported through sysfs */ #define CXACRU__ATTR_INIT(_name) \ static DEVICE_ATTR(_name, S_IRUGO, cxacru_sysfs_show_##_name, NULL) @@ -186,10 +189,16 @@ static ssize_t cxacru_sysfs_show_##_name } \ CXACRU__ATTR_INIT(_name) +#define CXACRU_CMD_INIT(_name) \ +static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \ + cxacru_sysfs_show_##_name, cxacru_sysfs_store_##_name) + #define CXACRU_ATTR_CREATE(_v, _t, _name) CXACRU_DEVICE_CREATE_FILE(_name) +#define CXACRU_CMD_CREATE(_name) CXACRU_DEVICE_CREATE_FILE(_name) #define CXACRU__ATTR_CREATE(_name) CXACRU_DEVICE_CREATE_FILE(_name) #define CXACRU_ATTR_REMOVE(_v, _t, _name) CXACRU_DEVICE_REMOVE_FILE(_name) +#define CXACRU_CMD_REMOVE(_name) CXACRU_DEVICE_REMOVE_FILE(_name) #define CXACRU__ATTR_REMOVE(_name) CXACRU_DEVICE_REMOVE_FILE(_name) static ssize_t cxacru_sysfs_showattr_u32(u32 value, char *buf) @@ -213,6 +222,7 @@ static ssize_t cxacru_sysfs_showattr_dB( } } +/* static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf) { switch (value) { @@ -221,6 +231,7 @@ static ssize_t cxacru_sysfs_showattr_boo default: return 0; } } +*/ static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf) { @@ -278,6 +289,66 @@ static ssize_t cxacru_sysfs_show_mac_add atm_dev->esi[3], atm_dev->esi[4], atm_dev->esi[5]); } + +static ssize_t cxacru_sysfs_show_adsl_running(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usbatm_data *usbatm_instance = usb_get_intfdata(intf); + struct cxacru_data *instance = usbatm_instance->driver_data; + + switch (instance->card_info[CXINF_LINE_STARTABLE]) { + case 0: return snprintf(buf, PAGE_SIZE, "yes\n"); + case 1: return snprintf(buf, PAGE_SIZE, "no\n"); + default: return 0; + } +} + +static ssize_t cxacru_sysfs_store_adsl_running(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int ret; + struct usb_interface *intf = to_usb_interface(dev); + struct usbatm_data *usbatm_instance = usb_get_intfdata(intf); + struct cxacru_data *instance = usbatm_instance->driver_data; + + if (!capable(CAP_NET_ADMIN)) + return -EACCES; + + switch (instance->card_info[CXINF_LINE_STARTABLE]) { + case 0: /* ADSL running */ + if (count != 3 + || strncmp(buf, "no", strlen("no")) + || strncmp(buf, "no\n", strlen("no\n"))) + return 0; + + ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_STOP, NULL, 0, NULL, 0); + if (ret < 0) { + atm_err(usbatm_instance, "cxacru_sysfs_store_atm_running:" + " CHIP_ADSL_LINE_STOP returned %d\n", ret); + return ret; + } + // TODO: poll twice more then stop + return strlen(buf); + case 1: /* ADSL not running */ + if (count != 4 + || strncmp(buf, "yes", strlen("yes")) + || strncmp(buf, "yes\n", strlen("yes\n"))) + return 0; + + ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0); + if (ret < 0) { + atm_err(usbatm_instance, "cxacru_sysfs_store_atm_running:" + " CHIP_ADSL_LINE_START returned %d\n", ret); + return ret; + } + // TODO: resume polling + return strlen(buf); + default: + return -EINVAL; + } +} + /* * All device attributes are included in CXACRU_ALL_FILES * so that the same list can be used multiple times: @@ -308,11 +379,11 @@ CXACRU_ATTR_##_action(CXINF_UPSTREAM_FEC CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_FEC_ERRORS, u32, downstream_fec_errors); \ CXACRU_ATTR_##_action(CXINF_UPSTREAM_HEC_ERRORS, u32, upstream_hec_errors); \ CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_HEC_ERRORS, u32, downstream_hec_errors); \ -CXACRU_ATTR_##_action(CXINF_LINE_STARTABLE, bool, line_startable); \ CXACRU_ATTR_##_action(CXINF_MODULATION, MODU, modulation); \ CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND, u32, adsl_headend); \ CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND_ENVIRONMENT, u32, adsl_headend_environment); \ -CXACRU_ATTR_##_action(CXINF_CONTROLLER_VERSION, u32, adsl_controller_version); +CXACRU_ATTR_##_action(CXINF_CONTROLLER_VERSION, u32, adsl_controller_version); \ +CXACRU_CMD_##_action( adsl_running); CXACRU_ALL_FILES(INIT); -- Simon Arlott
Attachment:
signature.asc
Description: OpenPGP digital signature
- References:
- [PATCH] cxacru: Export detailed device info through sysfs.
- From: Simon Arlott <[email protected]>
- [PATCH] cxacru: Export detailed device info through sysfs.
- Prev by Date: Re: PREEMPT_RCU breaks anon_vma locking ?
- Next by Date: Re: [KJ][RFC][PATCH] BIT macro cleanup
- Previous by thread: [PATCH] cxacru: Export detailed device info through sysfs.
- Next by thread: Re: [PATCH] cxacru: Export detailed device info through sysfs. (updated, card_info array one element too large)
- Index(es):