Am Freitag, den 04.05.2018, 08:00 -0500 schrieb David R. Bild : > > +config USB_XAPEA00X > + tristate "Xaptum ENF Access card support (XAP-EA-00x)" > + depends on USB_SUPPORT && SPI && TCG_TPM
You'd have to know how the device internally works. It would be better to select SPI. > +static int xapea00x_br_bulk_write(struct xapea00x_device *dev, > + struct xapea00x_br_bulk_command *header, > + const void *data, int len) > +{ > + u8 *buf; > + unsigned int pipe; > + int buf_len, actual_len, retval; > + > + buf_len = sizeof(struct xapea00x_br_bulk_command) + len; > + buf = kzalloc(buf_len, GFP_KERNEL); > + if (!buf) { > + retval = -ENOMEM; > + goto out; > + } > + > + memcpy(buf, header, sizeof(struct xapea00x_br_bulk_command)); > + memcpy(buf + sizeof(struct xapea00x_br_bulk_command), data, len); > + > + pipe = usb_sndbulkpipe(dev->udev, dev->bulk_out->bEndpointAddress); > + retval = usb_bulk_msg(dev->udev, pipe, buf, buf_len, &actual_len, > + XAPEA00X_BR_USB_TIMEOUT); > + if (retval) > + goto free_buf; WTF? > +free_buf: > + kzfree(buf); > + > +out: > + return retval; > +} > + [..] > +static int xapea00x_spi_setup(struct spi_device *spi) > +{ > + struct xapea00x_device *dev; > + int retval; > + > + dev = spi_master_get_devdata(spi->master); > + > + mutex_lock(&dev->usb_mutex); > + if (!dev->interface) { > + retval = -ENODEV; > + goto out; > + } > + > + /* Verify that this is the TPM device */ > + if (spi->chip_select != 0) { > + retval = -EINVAL; > + goto err; > + } > + > + /* > + * Disable auto chip select for the TPM channel. > + * Must be done after setting the SPI parameters. > + */ > + retval = xapea00x_br_disable_cs(dev, 0); > + if (retval) > + goto err; > + > + /* De-assert chip select for the TPM channel. */ > + retval = xapea00x_br_deassert_cs(dev, 0); > + if (retval) > + goto err; > + > + goto out; > + > +err: > + dev_err(&dev->interface->dev, > + "configuring SPI channel failed with %d\n", retval); That could be a simple 'if' statement. > + > +out: > + mutex_unlock(&dev->usb_mutex); > + return retval; > +} > + > [..] > +/** > + * xapea00x_spi_probe - Register and configure the SPI master. > + * @dev: the device whose SPI master to register > + * > + * Return: If successful, 0. Otherwise a negative error number. > + */ > +static int xapea00x_spi_probe(struct xapea00x_device *dev) > +{ > + struct spi_master *spi_master; > + int retval; > + > + spi_master = spi_alloc_master(&dev->interface->dev, sizeof(void *)); > + if (!spi_master) { > + retval = -ENOMEM; > + goto err_out; > + } > + > + spi_master_set_devdata(spi_master, dev); > + > + spi_master->min_speed_hz = 93 * 1000 + 800; /* 93.9kHz */ > + spi_master->max_speed_hz = 12 * 1000 * 1000; /* 12 MHz */ > + > + spi_master->bus_num = -1; /* dynamically assigned */ > + spi_master->num_chipselect = 1; > + spi_master->mode_bits = SPI_MODE_0; > + > + spi_master->flags = 0; > + spi_master->setup = xapea00x_spi_setup; > + spi_master->transfer_one_message = xapea00x_spi_transfer_one_message; > + > + retval = spi_register_master(spi_master); > + > + if (retval) > + goto free_spi; > + > + dev->spi_master = spi_master; Race condition. > + > + return 0; > + > +free_spi: > + spi_master_put(spi_master); > + dev->spi_master = NULL; > + > +err_out: > + return retval; > +} > + > +struct xapea00x_async_probe { > + struct work_struct work; > + struct xapea00x_device *dev; > +}; > + > +#define work_to_probe(w) container_of(w, struct xapea00x_async_probe, work) > + > +/** > + * xapea00x_init_async_probe - initialize an async probe with the > + * specified values. > + * @probe: pointer to the async_probe to initialize > + * @dev: pointer to the device to probe > + * @f: pointer to the probe function > + */ > +static void xapea00x_init_async_probe(struct xapea00x_async_probe *probe, > + struct xapea00x_device *dev, > + void (*f)(struct work_struct *work)) > +{ > + INIT_WORK(&probe->work, f); > + probe->dev = dev; > + > + kref_get(&dev->kref); > + spi_master_get(dev->spi_master); > +} > + > +/** > + * xapea00x_cleanup_async_probe - clean up the internals of the async > + * probe. Call this method after the probe has completed. > + * > + * The caller is responsible for freeing the probe itself, if > + * dynamically allocated. > + * > + * @probe: pointer to the async_probe to clean up > + */ > +static void xapea00x_cleanup_async_probe(struct xapea00x_async_probe *probe) > +{ > + spi_master_put(probe->dev->spi_master); > + kref_put(&probe->dev->kref, xapea00x_delete); > +} > + > +static struct spi_board_info tpm_board_info = { > + .modalias = XAPEA00X_TPM_MODALIAS, > + .max_speed_hz = 43 * 1000 * 1000, // Hz Are you hardcoding HZ ? > + .chip_select = 0, > + .mode = SPI_MODE_0 > +}; Regards Oliver -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html