USB: option: convert interface blacklisting to bitfields
authorDan Williams <dcbw@redhat.com>
Tue, 13 Sep 2011 18:49:41 +0000 (13:49 -0500)
committerGreg Kroah-Hartman <gregkh@suse.de>
Sun, 18 Sep 2011 08:22:53 +0000 (01:22 -0700)
It's cleaner than the array stuff, and we're about to add a bunch
more blacklist entries.  Second, there are devices that need both
the sendsetup and the reserved interface blacklists, which the
current code can't accommodate.

Signed-off-by: Dan Williams <dcbw@redhat.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/serial/option.c

index fe22e90bc879551a912ebcbcbf974a83c4ae0cb9..d4fc3c38eee9ceb51002c0f1c5ba75bf6ea3a524 100644 (file)
@@ -475,31 +475,24 @@ enum option_blacklist_reason {
                OPTION_BLACKLIST_RESERVED_IF = 2
 };
 
+#define MAX_BL_NUM  8
 struct option_blacklist_info {
-       const u32 infolen;      /* number of interface numbers on blacklist */
-       const u8  *ifaceinfo;   /* pointer to the array holding the numbers */
-       enum option_blacklist_reason reason;
+       /* bitfield of interface numbers for OPTION_BLACKLIST_SENDSETUP */
+       const unsigned long sendsetup;
+       /* bitfield of interface numbers for OPTION_BLACKLIST_RESERVED_IF */
+       const unsigned long reserved;
 };
 
-static const u8 four_g_w14_no_sendsetup[] = { 0, 1 };
 static const struct option_blacklist_info four_g_w14_blacklist = {
-       .infolen = ARRAY_SIZE(four_g_w14_no_sendsetup),
-       .ifaceinfo = four_g_w14_no_sendsetup,
-       .reason = OPTION_BLACKLIST_SENDSETUP
+       .sendsetup = BIT(0) | BIT(1),
 };
 
-static const u8 alcatel_x200_no_sendsetup[] = { 0, 1 };
 static const struct option_blacklist_info alcatel_x200_blacklist = {
-       .infolen = ARRAY_SIZE(alcatel_x200_no_sendsetup),
-       .ifaceinfo = alcatel_x200_no_sendsetup,
-       .reason = OPTION_BLACKLIST_SENDSETUP
+       .sendsetup = BIT(0) | BIT(1),
 };
 
-static const u8 zte_k3765_z_no_sendsetup[] = { 0, 1, 2 };
 static const struct option_blacklist_info zte_k3765_z_blacklist = {
-       .infolen = ARRAY_SIZE(zte_k3765_z_no_sendsetup),
-       .ifaceinfo = zte_k3765_z_no_sendsetup,
-       .reason = OPTION_BLACKLIST_SENDSETUP
+       .sendsetup = BIT(0) | BIT(1) | BIT(2),
 };
 
 static const struct usb_device_id option_ids[] = {
@@ -1255,21 +1248,28 @@ static int option_probe(struct usb_serial *serial,
        return 0;
 }
 
-static enum option_blacklist_reason is_blacklisted(const u8 ifnum,
-                               const struct option_blacklist_info *blacklist)
+static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason,
+                          const struct option_blacklist_info *blacklist)
 {
-       const u8  *info;
-       int i;
+       unsigned long num;
+       const unsigned long *intf_list;
 
        if (blacklist) {
-               info = blacklist->ifaceinfo;
+               if (reason == OPTION_BLACKLIST_SENDSETUP)
+                       intf_list = &blacklist->sendsetup;
+               else if (reason == OPTION_BLACKLIST_RESERVED_IF)
+                       intf_list = &blacklist->reserved;
+               else {
+                       BUG_ON(reason);
+                       return false;
+               }
 
-               for (i = 0; i < blacklist->infolen; i++) {
-                       if (info[i] == ifnum)
-                               return blacklist->reason;
+               for_each_set_bit(num, intf_list, MAX_BL_NUM + 1) {
+                       if (num == ifnum)
+                               return true;
                }
        }
-       return OPTION_BLACKLIST_NONE;
+       return false;
 }
 
 static void option_instat_callback(struct urb *urb)
@@ -1343,9 +1343,8 @@ static int option_send_setup(struct usb_serial_port *port)
        int val = 0;
        dbg("%s", __func__);
 
-       if (is_blacklisted(ifNum,
-                          (struct option_blacklist_info *) intfdata->private)
-           == OPTION_BLACKLIST_SENDSETUP) {
+       if (is_blacklisted(ifNum, OPTION_BLACKLIST_SENDSETUP,
+                       (struct option_blacklist_info *) intfdata->private)) {
                dbg("No send_setup on blacklisted interface #%d\n", ifNum);
                return -EIO;
        }