summaryrefslogtreecommitdiff
path: root/drivers/usb/atm/cxacru.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/atm/cxacru.c')
-rw-r--r--drivers/usb/atm/cxacru.c298
1 files changed, 151 insertions, 147 deletions
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 8a7eb77233b4..68a8e9de8b4f 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/******************************************************************************
* cxacru.c - driver for USB ADSL modems based on
* Conexant AccessRunner chipset
@@ -6,21 +7,6 @@
* Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru)
* Copyright (C) 2007 Simon Arlott
* Copyright (C) 2009 Simon Arlott
- *
- * 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.
- *
******************************************************************************/
/*
@@ -35,16 +21,14 @@
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/slab.h>
-#include <linux/init.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/mutex.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include "usbatm.h"
#define DRIVER_AUTHOR "Roman Kagan, David Woodhouse, Duncan Sands, Simon Arlott"
-#define DRIVER_VERSION "0.4"
#define DRIVER_DESC "Conexant AccessRunner ADSL USB modem driver"
static const char cxacru_driver_name[] = "cxacru";
@@ -196,7 +180,7 @@ struct cxacru_data {
struct mutex poll_state_serialize;
enum cxacru_poll_state poll_state;
- /* contol handles */
+ /* control handles */
struct mutex cm_serialize;
u8 *rcv_buf;
u8 *snd_buf;
@@ -212,18 +196,16 @@ static void cxacru_poll_status(struct work_struct *work);
/* Card info exported through sysfs */
#define CXACRU__ATTR_INIT(_name) \
-static DEVICE_ATTR(_name, S_IRUGO, cxacru_sysfs_show_##_name, NULL)
+static DEVICE_ATTR_RO(_name)
#define CXACRU_CMD_INIT(_name) \
-static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \
- cxacru_sysfs_show_##_name, cxacru_sysfs_store_##_name)
+static DEVICE_ATTR_RW(_name)
#define CXACRU_SET_INIT(_name) \
-static DEVICE_ATTR(_name, S_IWUSR, \
- NULL, cxacru_sysfs_store_##_name)
+static DEVICE_ATTR_WO(_name)
#define CXACRU_ATTR_INIT(_value, _type, _name) \
-static ssize_t cxacru_sysfs_show_##_name(struct device *dev, \
+static ssize_t _name##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct cxacru_data *instance = to_usbatm_driver_data(\
@@ -248,12 +230,12 @@ CXACRU__ATTR_INIT(_name)
static ssize_t cxacru_sysfs_showattr_u32(u32 value, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%u\n", value);
+ return sprintf(buf, "%u\n", value);
}
static ssize_t cxacru_sysfs_showattr_s8(s8 value, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", value);
+ return sprintf(buf, "%d\n", value);
}
static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf)
@@ -271,17 +253,19 @@ static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf)
static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf)
{
static char *str[] = { "no", "yes" };
+
if (unlikely(value >= ARRAY_SIZE(str)))
- return snprintf(buf, PAGE_SIZE, "%u\n", value);
- return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
+ return sprintf(buf, "%u\n", value);
+ return sprintf(buf, "%s\n", str[value]);
}
static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf)
{
static char *str[] = { NULL, "not connected", "connected", "lost" };
+
if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
- return snprintf(buf, PAGE_SIZE, "%u\n", value);
- return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
+ return sprintf(buf, "%u\n", value);
+ return sprintf(buf, "%s\n", str[value]);
}
static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf)
@@ -291,8 +275,8 @@ static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf)
"waiting", "initialising"
};
if (unlikely(value >= ARRAY_SIZE(str)))
- return snprintf(buf, PAGE_SIZE, "%u\n", value);
- return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
+ return sprintf(buf, "%u\n", value);
+ return sprintf(buf, "%s\n", str[value]);
}
static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf)
@@ -304,8 +288,8 @@ static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf)
"ITU-T G.992.2 (G.LITE)"
};
if (unlikely(value >= ARRAY_SIZE(str)))
- return snprintf(buf, PAGE_SIZE, "%u\n", value);
- return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
+ return sprintf(buf, "%u\n", value);
+ return sprintf(buf, "%s\n", str[value]);
}
/*
@@ -316,7 +300,7 @@ static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf)
* MAC_ADDRESS_LOW = 0x33221100
* Where 00-55 are bytes 0-5 of the MAC.
*/
-static ssize_t cxacru_sysfs_show_mac_address(struct device *dev,
+static ssize_t mac_address_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct cxacru_data *instance = to_usbatm_driver_data(
@@ -325,11 +309,10 @@ static ssize_t cxacru_sysfs_show_mac_address(struct device *dev,
if (instance == NULL || instance->usbatm->atm_dev == NULL)
return -ENODEV;
- return snprintf(buf, PAGE_SIZE, "%pM\n",
- instance->usbatm->atm_dev->esi);
+ return sprintf(buf, "%pM\n", instance->usbatm->atm_dev->esi);
}
-static ssize_t cxacru_sysfs_show_adsl_state(struct device *dev,
+static ssize_t adsl_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
static char *str[] = { "running", "stopped" };
@@ -342,11 +325,11 @@ static ssize_t cxacru_sysfs_show_adsl_state(struct device *dev,
value = instance->card_info[CXINF_LINE_STARTABLE];
if (unlikely(value >= ARRAY_SIZE(str)))
- return snprintf(buf, PAGE_SIZE, "%u\n", value);
- return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
+ return sprintf(buf, "%u\n", value);
+ return sprintf(buf, "%s\n", str[value]);
}
-static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev,
+static ssize_t adsl_state_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct cxacru_data *instance = to_usbatm_driver_data(
@@ -424,6 +407,7 @@ static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev,
case CXPOLL_STOPPING:
/* abort stop request */
instance->poll_state = CXPOLL_POLLING;
+ fallthrough;
case CXPOLL_POLLING:
case CXPOLL_SHUTDOWN:
/* don't start polling */
@@ -448,7 +432,7 @@ static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev,
/* CM_REQUEST_CARD_DATA_GET times out, so no show attribute */
-static ssize_t cxacru_sysfs_store_adsl_config(struct device *dev,
+static ssize_t adsl_config_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct cxacru_data *instance = to_usbatm_driver_data(
@@ -473,7 +457,9 @@ static ssize_t cxacru_sysfs_store_adsl_config(struct device *dev,
ret = sscanf(buf + pos, "%x=%x%n", &index, &value, &tmp);
if (ret < 2)
return -EINVAL;
- if (index < 0 || index > 0x7f)
+ if (index > 0x7f)
+ return -EINVAL;
+ if (tmp < 0 || tmp > len - pos)
return -EINVAL;
pos += tmp;
@@ -552,29 +538,67 @@ CXACRU_SET_##_action( adsl_config);
CXACRU_ALL_FILES(INIT);
+static struct attribute *cxacru_attrs[] = {
+ &dev_attr_adsl_config.attr,
+ &dev_attr_adsl_state.attr,
+ &dev_attr_adsl_controller_version.attr,
+ &dev_attr_adsl_headend_environment.attr,
+ &dev_attr_adsl_headend.attr,
+ &dev_attr_modulation.attr,
+ &dev_attr_line_startable.attr,
+ &dev_attr_downstream_hec_errors.attr,
+ &dev_attr_upstream_hec_errors.attr,
+ &dev_attr_downstream_fec_errors.attr,
+ &dev_attr_upstream_fec_errors.attr,
+ &dev_attr_downstream_crc_errors.attr,
+ &dev_attr_upstream_crc_errors.attr,
+ &dev_attr_startup_attempts.attr,
+ &dev_attr_downstream_bits_per_frame.attr,
+ &dev_attr_upstream_bits_per_frame.attr,
+ &dev_attr_transmitter_power.attr,
+ &dev_attr_downstream_attenuation.attr,
+ &dev_attr_upstream_attenuation.attr,
+ &dev_attr_downstream_snr_margin.attr,
+ &dev_attr_upstream_snr_margin.attr,
+ &dev_attr_mac_address.attr,
+ &dev_attr_line_status.attr,
+ &dev_attr_link_status.attr,
+ &dev_attr_upstream_rate.attr,
+ &dev_attr_downstream_rate.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(cxacru);
+
/* the following three functions are stolen from drivers/usb/core/message.c */
static void cxacru_blocking_completion(struct urb *urb)
{
complete(urb->context);
}
-static void cxacru_timeout_kill(unsigned long data)
+struct cxacru_timer {
+ struct timer_list timer;
+ struct urb *urb;
+};
+
+static void cxacru_timeout_kill(struct timer_list *t)
{
- usb_unlink_urb((struct urb *) data);
+ struct cxacru_timer *timer = timer_container_of(timer, t, timer);
+
+ usb_unlink_urb(timer->urb);
}
static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
int *actual_length)
{
- struct timer_list timer;
+ struct cxacru_timer timer = {
+ .urb = urb,
+ };
- init_timer(&timer);
- timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT);
- timer.data = (unsigned long) urb;
- timer.function = cxacru_timeout_kill;
- add_timer(&timer);
+ timer_setup_on_stack(&timer.timer, cxacru_timeout_kill, 0);
+ mod_timer(&timer.timer, jiffies + msecs_to_jiffies(CMD_TIMEOUT));
wait_for_completion(done);
- del_timer_sync(&timer);
+ timer_delete_sync(&timer.timer);
+ timer_destroy_on_stack(&timer.timer);
if (actual_length)
*actual_length = urb->actual_length;
@@ -703,6 +727,7 @@ static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_requ
len = ret / 4;
for (offb = 0; offb < len; ) {
int l = le32_to_cpu(buf[offb++]);
+
if (l < 0 || l > stride || l > (len - offb) / 2) {
if (printk_ratelimit())
usb_err(instance->usbatm, "invalid data length from cm %#x: %d\n",
@@ -733,6 +758,7 @@ cleanup:
static int cxacru_card_status(struct cxacru_data *instance)
{
int ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
+
if (ret < 0) { /* firmware not loaded */
usb_dbg(instance->usbatm, "cxacru_adsl_start: CARD_GET_STATUS returned %d\n", ret);
return ret;
@@ -740,17 +766,6 @@ static int cxacru_card_status(struct cxacru_data *instance)
return 0;
}
-static void cxacru_remove_device_files(struct usbatm_data *usbatm_instance,
- struct atm_dev *atm_dev)
-{
- struct usb_interface *intf = usbatm_instance->usb_intf;
-
- #define CXACRU_DEVICE_REMOVE_FILE(_name) \
- device_remove_file(&intf->dev, &dev_attr_##_name);
- CXACRU_ALL_FILES(REMOVE);
- #undef CXACRU_DEVICE_REMOVE_FILE
-}
-
static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
struct atm_dev *atm_dev)
{
@@ -769,13 +784,6 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
return ret;
}
- #define CXACRU_DEVICE_CREATE_FILE(_name) \
- ret = device_create_file(&intf->dev, &dev_attr_##_name); \
- if (unlikely(ret)) \
- goto fail_sysfs;
- CXACRU_ALL_FILES(CREATE);
- #undef CXACRU_DEVICE_CREATE_FILE
-
/* start ADSL */
mutex_lock(&instance->adsl_state_serialize);
ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
@@ -793,6 +801,7 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
case CXPOLL_STOPPING:
/* abort stop request */
instance->poll_state = CXPOLL_POLLING;
+ fallthrough;
case CXPOLL_POLLING:
case CXPOLL_SHUTDOWN:
/* don't start polling */
@@ -801,17 +810,9 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
mutex_unlock(&instance->poll_state_serialize);
mutex_unlock(&instance->adsl_state_serialize);
- printk(KERN_INFO "%s%d: %s %pM\n", atm_dev->type, atm_dev->number,
- usbatm_instance->description, atm_dev->esi);
-
if (start_polling)
cxacru_poll_status(&instance->poll_work.work);
return 0;
-
-fail_sysfs:
- usb_err(usbatm_instance, "cxacru_atm_start: device_create_file failed (%d)\n", ret);
- cxacru_remove_device_files(usbatm_instance, atm_dev);
- return ret;
}
static void cxacru_poll_status(struct work_struct *work)
@@ -848,15 +849,15 @@ static void cxacru_poll_status(struct work_struct *work)
switch (instance->adsl_status) {
case 0:
- atm_printk(KERN_INFO, usbatm, "ADSL state: running\n");
+ atm_info(usbatm, "ADSL state: running\n");
break;
case 1:
- atm_printk(KERN_INFO, usbatm, "ADSL state: stopped\n");
+ atm_info(usbatm, "ADSL state: stopped\n");
break;
default:
- atm_printk(KERN_INFO, usbatm, "Unknown adsl status %02x\n", instance->adsl_status);
+ atm_info(usbatm, "Unknown adsl status %02x\n", instance->adsl_status);
break;
}
}
@@ -946,6 +947,7 @@ static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw,
offb = offd = 0;
do {
int l = min_t(int, stride, size - offd);
+
buf[offb++] = fw;
buf[offb++] = l;
buf[offb++] = code1;
@@ -978,25 +980,60 @@ cleanup:
return ret;
}
-static void cxacru_upload_firmware(struct cxacru_data *instance,
- const struct firmware *fw,
- const struct firmware *bp)
+
+static int cxacru_find_firmware(struct cxacru_data *instance,
+ char *phase, const struct firmware **fw_p)
{
- int ret;
+ struct usbatm_data *usbatm = instance->usbatm;
+ struct device *dev = &usbatm->usb_intf->dev;
+ char buf[16];
+
+ sprintf(buf, "cxacru-%s.bin", phase);
+ usb_dbg(usbatm, "cxacru_find_firmware: looking for %s\n", buf);
+
+ if (request_firmware(fw_p, buf, dev)) {
+ usb_dbg(usbatm, "no stage %s firmware found\n", phase);
+ return -ENOENT;
+ }
+
+ usb_info(usbatm, "found firmware %s\n", buf);
+
+ return 0;
+}
+
+static int cxacru_heavy_init(struct usbatm_data *usbatm_instance,
+ struct usb_interface *usb_intf)
+{
+ const struct firmware *fw, *bp;
+ struct cxacru_data *instance = usbatm_instance->driver_data;
struct usbatm_data *usbatm = instance->usbatm;
struct usb_device *usb_dev = usbatm->usb_dev;
__le16 signature[] = { usb_dev->descriptor.idVendor,
usb_dev->descriptor.idProduct };
__le32 val;
+ int ret;
- usb_dbg(usbatm, "%s\n", __func__);
+ ret = cxacru_find_firmware(instance, "fw", &fw);
+ if (ret) {
+ usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n");
+ return ret;
+ }
+
+ if (instance->modem_type->boot_rom_patch) {
+ ret = cxacru_find_firmware(instance, "bp", &bp);
+ if (ret) {
+ usb_warn(usbatm_instance, "boot ROM patch (cxacru-bp.bin) unavailable (system misconfigured?)\n");
+ release_firmware(fw);
+ return ret;
+ }
+ }
/* FirmwarePllFClkValue */
val = cpu_to_le32(instance->modem_type->pll_f_clk);
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4);
if (ret) {
usb_err(usbatm, "FirmwarePllFClkValue failed: %d\n", ret);
- return;
+ goto done;
}
/* FirmwarePllBClkValue */
@@ -1004,7 +1041,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4);
if (ret) {
usb_err(usbatm, "FirmwarePllBClkValue failed: %d\n", ret);
- return;
+ goto done;
}
/* Enable SDRAM */
@@ -1012,7 +1049,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4);
if (ret) {
usb_err(usbatm, "Enable SDRAM failed: %d\n", ret);
- return;
+ goto done;
}
/* Firmware */
@@ -1020,7 +1057,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size);
if (ret) {
usb_err(usbatm, "Firmware upload failed: %d\n", ret);
- return;
+ goto done;
}
/* Boot ROM patch */
@@ -1029,7 +1066,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size);
if (ret) {
usb_err(usbatm, "Boot ROM patching failed: %d\n", ret);
- return;
+ goto done;
}
}
@@ -1037,7 +1074,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4);
if (ret) {
usb_err(usbatm, "Signature storing failed: %d\n", ret);
- return;
+ goto done;
}
usb_info(usbatm, "starting device\n");
@@ -1049,7 +1086,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
}
if (ret) {
usb_err(usbatm, "Passing control to firmware failed: %d\n", ret);
- return;
+ goto done;
}
/* Delay to allow firmware to start up. */
@@ -1063,53 +1100,10 @@ static void cxacru_upload_firmware(struct cxacru_data *instance,
ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
if (ret < 0) {
usb_err(usbatm, "modem failed to initialize: %d\n", ret);
- return;
- }
-}
-
-static int cxacru_find_firmware(struct cxacru_data *instance,
- char *phase, const struct firmware **fw_p)
-{
- struct usbatm_data *usbatm = instance->usbatm;
- struct device *dev = &usbatm->usb_intf->dev;
- char buf[16];
-
- sprintf(buf, "cxacru-%s.bin", phase);
- usb_dbg(usbatm, "cxacru_find_firmware: looking for %s\n", buf);
-
- if (request_firmware(fw_p, buf, dev)) {
- usb_dbg(usbatm, "no stage %s firmware found\n", phase);
- return -ENOENT;
- }
-
- usb_info(usbatm, "found firmware %s\n", buf);
-
- return 0;
-}
-
-static int cxacru_heavy_init(struct usbatm_data *usbatm_instance,
- struct usb_interface *usb_intf)
-{
- const struct firmware *fw, *bp;
- struct cxacru_data *instance = usbatm_instance->driver_data;
-
- int ret = cxacru_find_firmware(instance, "fw", &fw);
- if (ret) {
- usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n");
- return ret;
+ goto done;
}
- if (instance->modem_type->boot_rom_patch) {
- ret = cxacru_find_firmware(instance, "bp", &bp);
- if (ret) {
- usb_warn(usbatm_instance, "boot ROM patch (cxacru-bp.bin) unavailable (system misconfigured?)\n");
- release_firmware(fw);
- return ret;
- }
- }
-
- cxacru_upload_firmware(instance, fw, bp);
-
+done:
if (instance->modem_type->boot_rom_patch)
release_firmware(bp);
release_firmware(fw);
@@ -1129,14 +1123,16 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
struct cxacru_data *instance;
struct usb_device *usb_dev = interface_to_usbdev(intf);
struct usb_host_endpoint *cmd_ep = usb_dev->ep_in[CXACRU_EP_CMD];
+ static const u8 ep_addrs[] = {
+ CXACRU_EP_CMD + USB_DIR_IN,
+ CXACRU_EP_CMD + USB_DIR_OUT,
+ 0};
int ret;
/* instance init */
instance = kzalloc(sizeof(*instance), GFP_KERNEL);
- if (!instance) {
- usb_dbg(usbatm_instance, "cxacru_bind: no memory for instance data\n");
+ if (!instance)
return -ENOMEM;
- }
instance->usbatm = usbatm_instance;
instance->modem_type = (struct cxacru_modem_type *) id->driver_info;
@@ -1162,13 +1158,11 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
}
instance->rcv_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!instance->rcv_urb) {
- usb_dbg(usbatm_instance, "cxacru_bind: no memory for rcv_urb\n");
ret = -ENOMEM;
goto fail;
}
instance->snd_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!instance->snd_urb) {
- usb_dbg(usbatm_instance, "cxacru_bind: no memory for snd_urb\n");
ret = -ENOMEM;
goto fail;
}
@@ -1179,6 +1173,17 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
goto fail;
}
+ if (usb_endpoint_xfer_int(&cmd_ep->desc))
+ ret = usb_check_int_endpoints(intf, ep_addrs);
+ else
+ ret = usb_check_bulk_endpoints(intf, ep_addrs);
+
+ if (!ret) {
+ usb_err(usbatm_instance, "cxacru_bind: interface has incorrect endpoints\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+
if ((cmd_ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_INT) {
usb_fill_int_urb(instance->rcv_urb,
@@ -1338,7 +1343,6 @@ static struct usbatm_driver cxacru_driver = {
.heavy_init = cxacru_heavy_init,
.unbind = cxacru_unbind,
.atm_start = cxacru_atm_start,
- .atm_stop = cxacru_remove_device_files,
.bulk_in = CXACRU_EP_DATA,
.bulk_out = CXACRU_EP_DATA,
.rx_padding = 3,
@@ -1370,7 +1374,8 @@ static struct usb_driver cxacru_usb_driver = {
.name = cxacru_driver_name,
.probe = cxacru_usb_probe,
.disconnect = usbatm_usb_disconnect,
- .id_table = cxacru_usb_ids
+ .id_table = cxacru_usb_ids,
+ .dev_groups = cxacru_groups,
};
module_usb_driver(cxacru_usb_driver);
@@ -1378,4 +1383,3 @@ module_usb_driver(cxacru_usb_driver);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION);