LCOV - code coverage report
Current view: top level - drivers/usb/storage - uas-detect.h (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 0 51 0.0 %
Date: 2020-09-30 20:25:40 Functions: 0 2 0.0 %
Branches: 0 46 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: GPL-2.0 */
       2                 :            : #include <linux/usb.h>
       3                 :            : #include <linux/usb/hcd.h>
       4                 :            : #include "usb.h"
       5                 :            : 
       6                 :            : static int uas_is_interface(struct usb_host_interface *intf)
       7                 :            : {
       8                 :            :         return (intf->desc.bInterfaceClass == USB_CLASS_MASS_STORAGE &&
       9                 :          0 :                 intf->desc.bInterfaceSubClass == USB_SC_SCSI &&
      10                 :            :                 intf->desc.bInterfaceProtocol == USB_PR_UAS);
      11                 :            : }
      12                 :            : 
      13                 :            : static struct usb_host_interface *uas_find_uas_alt_setting(
      14                 :            :                 struct usb_interface *intf)
      15                 :            : {
      16                 :            :         int i;
      17                 :            : 
      18         [ #  # ]:          0 :         for (i = 0; i < intf->num_altsetting; i++) {
      19                 :          0 :                 struct usb_host_interface *alt = &intf->altsetting[i];
      20                 :            : 
      21         [ #  # ]:          0 :                 if (uas_is_interface(alt))
      22                 :          0 :                         return alt;
      23                 :            :         }
      24                 :            : 
      25                 :            :         return NULL;
      26                 :            : }
      27                 :            : 
      28                 :          0 : static int uas_find_endpoints(struct usb_host_interface *alt,
      29                 :            :                               struct usb_host_endpoint *eps[])
      30                 :            : {
      31                 :          0 :         struct usb_host_endpoint *endpoint = alt->endpoint;
      32                 :          0 :         unsigned i, n_endpoints = alt->desc.bNumEndpoints;
      33                 :            : 
      34         [ #  # ]:          0 :         for (i = 0; i < n_endpoints; i++) {
      35                 :          0 :                 unsigned char *extra = endpoint[i].extra;
      36                 :          0 :                 int len = endpoint[i].extralen;
      37         [ #  # ]:          0 :                 while (len >= 3) {
      38         [ #  # ]:          0 :                         if (extra[1] == USB_DT_PIPE_USAGE) {
      39                 :          0 :                                 unsigned pipe_id = extra[2];
      40         [ #  # ]:          0 :                                 if (pipe_id > 0 && pipe_id < 5)
      41                 :          0 :                                         eps[pipe_id - 1] = &endpoint[i];
      42                 :            :                                 break;
      43                 :            :                         }
      44                 :          0 :                         len -= extra[0];
      45                 :          0 :                         extra += extra[0];
      46                 :            :                 }
      47                 :            :         }
      48                 :            : 
      49   [ #  #  #  #  :          0 :         if (!eps[0] || !eps[1] || !eps[2] || !eps[3])
             #  #  #  # ]
      50                 :            :                 return -ENODEV;
      51                 :            : 
      52                 :          0 :         return 0;
      53                 :            : }
      54                 :            : 
      55                 :          0 : static int uas_use_uas_driver(struct usb_interface *intf,
      56                 :            :                               const struct usb_device_id *id,
      57                 :            :                               unsigned long *flags_ret)
      58                 :            : {
      59                 :          0 :         struct usb_host_endpoint *eps[4] = { };
      60                 :            :         struct usb_device *udev = interface_to_usbdev(intf);
      61                 :          0 :         struct usb_hcd *hcd = bus_to_hcd(udev->bus);
      62                 :          0 :         unsigned long flags = id->driver_info;
      63                 :            :         struct usb_host_interface *alt;
      64                 :            :         int r;
      65                 :            : 
      66                 :            :         alt = uas_find_uas_alt_setting(intf);
      67         [ #  # ]:          0 :         if (!alt)
      68                 :            :                 return 0;
      69                 :            : 
      70                 :          0 :         r = uas_find_endpoints(alt, eps);
      71         [ #  # ]:          0 :         if (r < 0)
      72                 :            :                 return 0;
      73                 :            : 
      74                 :            :         /*
      75                 :            :          * ASMedia has a number of usb3 to sata bridge chips, at the time of
      76                 :            :          * this writing the following versions exist:
      77                 :            :          * ASM1051 - no uas support version
      78                 :            :          * ASM1051 - with broken (*) uas support
      79                 :            :          * ASM1053 - with working uas support, but problems with large xfers
      80                 :            :          * ASM1153 - with working uas support
      81                 :            :          *
      82                 :            :          * Devices with these chips re-use a number of device-ids over the
      83                 :            :          * entire line, so the device-id is useless to determine if we're
      84                 :            :          * dealing with an ASM1051 (which we want to avoid).
      85                 :            :          *
      86                 :            :          * The ASM1153 can be identified by config.MaxPower == 0,
      87                 :            :          * where as the ASM105x models have config.MaxPower == 36.
      88                 :            :          *
      89                 :            :          * Differentiating between the ASM1053 and ASM1051 is trickier, when
      90                 :            :          * connected over USB-3 we can look at the number of streams supported,
      91                 :            :          * ASM1051 supports 32 streams, where as early ASM1053 versions support
      92                 :            :          * 16 streams, newer ASM1053-s also support 32 streams, but have a
      93                 :            :          * different prod-id.
      94                 :            :          *
      95                 :            :          * (*) ASM1051 chips do work with UAS with some disks (with the
      96                 :            :          *     US_FL_NO_REPORT_OPCODES quirk), but are broken with other disks
      97                 :            :          */
      98   [ #  #  #  # ]:          0 :         if (le16_to_cpu(udev->descriptor.idVendor) == 0x174c &&
      99                 :          0 :                         (le16_to_cpu(udev->descriptor.idProduct) == 0x5106 ||
     100                 :            :                          le16_to_cpu(udev->descriptor.idProduct) == 0x55aa)) {
     101         [ #  # ]:          0 :                 if (udev->actconfig->desc.bMaxPower == 0) {
     102                 :            :                         /* ASM1153, do nothing */
     103         [ #  # ]:          0 :                 } else if (udev->speed < USB_SPEED_SUPER) {
     104                 :            :                         /* No streams info, assume ASM1051 */
     105                 :          0 :                         flags |= US_FL_IGNORE_UAS;
     106         [ #  # ]:          0 :                 } else if (usb_ss_max_streams(&eps[1]->ss_ep_comp) == 32) {
     107                 :            :                         /* Possibly an ASM1051, disable uas */
     108                 :          0 :                         flags |= US_FL_IGNORE_UAS;
     109                 :            :                 } else {
     110                 :            :                         /* ASM1053, these have issues with large transfers */
     111                 :          0 :                         flags |= US_FL_MAX_SECTORS_240;
     112                 :            :                 }
     113                 :            :         }
     114                 :            : 
     115                 :            :         /* All Seagate disk enclosures have broken ATA pass-through support */
     116         [ #  # ]:          0 :         if (le16_to_cpu(udev->descriptor.idVendor) == 0x0bc2)
     117                 :          0 :                 flags |= US_FL_NO_ATA_1X;
     118                 :            : 
     119                 :          0 :         usb_stor_adjust_quirks(udev, &flags);
     120                 :            : 
     121         [ #  # ]:          0 :         if (flags & US_FL_IGNORE_UAS) {
     122                 :          0 :                 dev_warn(&udev->dev,
     123                 :            :                         "UAS is blacklisted for this device, using usb-storage instead\n");
     124                 :          0 :                 return 0;
     125                 :            :         }
     126                 :            : 
     127         [ #  # ]:          0 :         if (udev->bus->sg_tablesize == 0) {
     128                 :          0 :                 dev_warn(&udev->dev,
     129                 :            :                         "The driver for the USB controller %s does not support scatter-gather which is\n",
     130                 :            :                         hcd->driver->description);
     131                 :          0 :                 dev_warn(&udev->dev,
     132                 :            :                         "required by the UAS driver. Please try an other USB controller if you wish to use UAS.\n");
     133                 :          0 :                 return 0;
     134                 :            :         }
     135                 :            : 
     136   [ #  #  #  # ]:          0 :         if (udev->speed >= USB_SPEED_SUPER && !hcd->can_do_streams) {
     137                 :          0 :                 dev_warn(&udev->dev,
     138                 :            :                         "USB controller %s does not support streams, which are required by the UAS driver.\n",
     139                 :            :                         hcd_to_bus(hcd)->bus_name);
     140                 :          0 :                 dev_warn(&udev->dev,
     141                 :            :                         "Please try an other USB controller if you wish to use UAS.\n");
     142                 :          0 :                 return 0;
     143                 :            :         }
     144                 :            : 
     145         [ #  # ]:          0 :         if (flags_ret)
     146                 :          0 :                 *flags_ret = flags;
     147                 :            : 
     148                 :            :         return 1;
     149                 :            : }

Generated by: LCOV version 1.14