Re: [RFC PATCH v2] Xilinx AXI-Stream FIFO v4.1 IP core driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This version is much much better.

On Sun, Jul 15, 2018 at 12:34:28PM -0400, Jacob Feder wrote:
> +static ssize_t sysfs_write(struct device *dev, const char *buf,
> +			   size_t count, unsigned int addr_offset)
> +{
> +	struct axis_fifo *fifo = dev_get_drvdata(dev);
> +	unsigned long tmp;
> +
> +	if (kstrtoul(buf, 0, &tmp))
> +		return -EINVAL;

It's better to preserve the error code from kstrtoul().  I wouldn't
comment on this except there are a bunch of places which need to
preserve the error code.

> +
> +	iowrite32(tmp, fifo->base_addr + addr_offset);
> +
> +	return count;
> +}
> +
> +static ssize_t sysfs_read(struct device *dev, char *buf,
> +			  unsigned int addr_offset)
> +{
> +	struct axis_fifo *fifo = dev_get_drvdata(dev);
> +	unsigned int read_val;
> +	unsigned int strlen;
> +	char tmp[32];
> +
> +	read_val = ioread32(fifo->base_addr + addr_offset);
> +
> +	strlen =  snprintf(tmp, 32, "0x%08x\n", read_val);
> +	if (strlen < 0)
> +		return -EINVAL;

Kernel snprintf() won't ever return error codes, so this check is not
required...  Just delete it.  Or at least preserve the error code.

> +
> +	memcpy(buf, tmp, strlen);
> +
> +	return strlen;
> +}
> +


> +static void reset_ip_core(struct axis_fifo *fifo)
> +{
> +	iowrite32(XLLF_SRR_RESET_MASK,
> +		  fifo->base_addr + XLLF_SRR_OFFSET);
> +	iowrite32(XLLF_TDFR_RESET_MASK,
> +		  fifo->base_addr + XLLF_TDFR_OFFSET);
> +	iowrite32(XLLF_RDFR_RESET_MASK,
> +		  fifo->base_addr + XLLF_RDFR_OFFSET);

These can fit in 80 characters now.

	iowrite32(XLLF_RDFR_RESET_MASK, fifo->base_addr + XLLF_RDFR_OFFSET);

> +	iowrite32(XLLF_INT_TC_MASK | XLLF_INT_RC_MASK | XLLF_INT_RPURE_MASK |
> +		  XLLF_INT_RPORE_MASK | XLLF_INT_RPUE_MASK |
> +		  XLLF_INT_TPOE_MASK | XLLF_INT_TSE_MASK,
> +		  fifo->base_addr + XLLF_IER_OFFSET);
> +	iowrite32(XLLF_INT_ALL_MASK,
> +		  fifo->base_addr + XLLF_ISR_OFFSET);
> +}
> +
> +/* reads a single packet from the fifo as dictated by the tlast signal */
> +static ssize_t axis_fifo_read(struct file *f, char __user *buf,
> +			      size_t len, loff_t *off)
> +{
> +	struct axis_fifo *fifo = (struct axis_fifo *)f->private_data;
> +	unsigned int bytes_available;
> +	unsigned int words_available;
> +	unsigned int copied;
> +	unsigned int copy;
> +	unsigned int i;
> +	int ret;
> +	u32 tmp_buf[READ_BUF_SIZE];
> +
> +	if (fifo->read_flags & O_NONBLOCK) {
> +		/* opened in non-blocking mode
> +		 * return if there are no packets available
> +		 */
> +		if (!ioread32(fifo->base_addr + XLLF_RDFO_OFFSET))
> +			return -EAGAIN;
> +	} else {
> +		/* opened in blocking mode
> +		 * wait for a packet available interrupt (or timeout)
> +		 * if nothing is currently available
> +		 */
> +		spin_lock_irq(&fifo->read_queue_lock);
> +		if (read_timeout < 0) {
> +			ret = wait_event_interruptible_lock_irq_timeout(
> +				fifo->read_queue,
> +				ioread32(fifo->base_addr + XLLF_RDFO_OFFSET),
> +				fifo->read_queue_lock, MAX_SCHEDULE_TIMEOUT);
> +		} else {
> +			ret = wait_event_interruptible_lock_irq_timeout(
> +				fifo->read_queue,
> +				ioread32(fifo->base_addr + XLLF_RDFO_OFFSET),
> +				fifo->read_queue_lock,
> +				msecs_to_jiffies(read_timeout));
> +		}


I'm not a huge fan of ternaries but they would help here:

                ret = wait_event_interruptible_lock_irq_timeout(
                        fifo->read_queue,
                        ioread32(fifo->base_addr + XLLF_RDFO_OFFSET),
                        fifo->read_queue_lock,
                        (read_timeout >= 0) ? msecs_to_jiffies(read_timeout) :
                                              MAX_SCHEDULE_TIMEOUT);


> +		spin_unlock_irq(&fifo->read_queue_lock);
> +
> +		if (ret == 0) {
> +			/* timeout occurred */
> +			dev_dbg(fifo->dt_device, "read timeout");
> +			return -EAGAIN;
> +		} else if (ret == -ERESTARTSYS) {
> +			/* signal received */
> +			return -ERESTARTSYS;
> +		} else if (ret < 0) {
> +			dev_err(fifo->dt_device, "wait_event_interruptible_timeout() error in read (ret=%i)\n",
> +				ret);
> +			return ret;
> +		}
> +	}
> +
> +	bytes_available = ioread32(fifo->base_addr + XLLF_RLR_OFFSET);
> +	if (!bytes_available) {
> +		dev_err(fifo->dt_device, "received a packet of length 0 - fifo core will be reset\n");
> +		reset_ip_core(fifo);
> +		return -EIO;
> +	}
> +
> +	if (bytes_available > len) {
> +		dev_err(fifo->dt_device, "user read buffer too small (available bytes=%u user buffer bytes=%u) - fifo core will be reset\n",
> +			bytes_available, len);
> +		reset_ip_core(fifo);
> +		return -EINVAL;
> +	}
> +
> +	if (bytes_available % sizeof(u32)) {
> +		/* this probably can't happen unless IP
> +		 * registers were previously mishandled
> +		 */
> +		dev_err(fifo->dt_device, "received a packet that isn't word-aligned - fifo core will be reset\n");
> +		reset_ip_core(fifo);
> +		return -EIO;
> +	}
> +
> +	words_available = bytes_available / sizeof(u32);
> +
> +	/* read data into an intermediate buffer, copying the contents
> +	 * to userspace when the buffer is full
> +	 */
> +	copied = 0;
> +	while (words_available > 0) {
> +		copy = min(words_available, READ_BUF_SIZE);
> +
> +		for (i = 0; i < copy; i++) {
> +			tmp_buf[i] = ioread32(fifo->base_addr +
> +					      XLLF_RDFD_OFFSET);
> +		}
> +
> +		if (copy_to_user(buf + copied * sizeof(u32), tmp_buf,
> +				 copy * sizeof(u32))) {
> +			reset_ip_core(fifo);
> +			return -EFAULT;
> +		}
> +
> +		copied += copy;
> +		words_available -= copy;
> +	}
> +
> +	return bytes_available;
> +}
> +
> +static ssize_t axis_fifo_write(struct file *f, const char __user *buf,
> +			       size_t len, loff_t *off)
> +{
> +	struct axis_fifo *fifo = (struct axis_fifo *)f->private_data;
> +	unsigned int words_to_write;
> +	unsigned int copied;
> +	unsigned int copy;
> +	unsigned int i;
> +	int ret;
> +	u32 tmp_buf[WRITE_BUF_SIZE];
> +
> +	if (len % sizeof(u32)) {
> +		dev_err(fifo->dt_device,
> +			"tried to send a packet that isn't word-aligned\n");
> +		return -EINVAL;
> +	}
> +
> +	words_to_write = len / sizeof(u32);
> +
> +	if (!words_to_write) {
> +		dev_err(fifo->dt_device,
> +			"tried to send a packet of length 0\n");
> +		return -EINVAL;
> +	}
> +
> +	if (words_to_write > fifo->tx_fifo_depth) {
> +		dev_err(fifo->dt_device, "tried to write more words [%u] than slots in the fifo buffer [%u]\n",
> +			words_to_write, fifo->tx_fifo_depth);
> +		return -EINVAL;
> +	}
> +
> +	if (fifo->write_flags & O_NONBLOCK) {
> +		/* opened in non-blocking mode
> +		 * return if there is not enough room available in the fifo
> +		 */
> +		if (words_to_write > ioread32(fifo->base_addr +
> +						XLLF_TDFV_OFFSET)) {
> +			return -EAGAIN;
> +		}
> +	} else {
> +		/* opened in blocking mode */
> +
> +		/* wait for an interrupt (or timeout) if there isn't
> +		 * currently enough room in the fifo
> +		 */
> +		spin_lock_irq(&fifo->write_queue_lock);
> +		if (write_timeout < 0) {
> +			ret = wait_event_interruptible_lock_irq_timeout(
> +					fifo->write_queue,
> +					ioread32(fifo->base_addr +
> +						 XLLF_TDFV_OFFSET) >=
> +						 words_to_write,
> +					fifo->write_queue_lock,
> +					MAX_SCHEDULE_TIMEOUT);
> +		} else {
> +			ret = wait_event_interruptible_lock_irq_timeout(
> +					fifo->write_queue,
> +					ioread32(fifo->base_addr +
> +						 XLLF_TDFV_OFFSET) >=
> +						 words_to_write,
> +					fifo->write_queue_lock,
> +					msecs_to_jiffies(write_timeout));
> +		}

                ret = wait_event_interruptible_lock_irq_timeout(
                        fifo->write_queue,
                        ioread32(fifo->base_addr + XLLF_TDFV_OFFSET)
                                >= words_to_write,
                        fifo->write_queue_lock,
                        (write_timeout < 0) ? MAX_SCHEDULE_TIMEOUT :
                                              msecs_to_jiffies(write_timeout));


> +		spin_unlock_irq(&fifo->write_queue_lock);
> +
> +		if (ret == 0) {
> +			/* timeout occurred */
> +			dev_dbg(fifo->dt_device, "write timeout\n");
> +			return -EAGAIN;
> +		} else if (ret == -ERESTARTSYS) {
> +			/* signal received */
> +			return -ERESTARTSYS;
> +		} else if (ret < 0) {
> +			/* unknown error */
> +			dev_err(fifo->dt_device,
> +				"wait_event_interruptible_timeout() error in write (ret=%i)\n",
> +				ret);
> +			return ret;
> +		}
> +	}
> +
> +	/* write data from an intermediate buffer into the fifo IP, refilling
> +	 * the buffer with userspace data as needed
> +	 */
> +	copied = 0;
> +	while (words_to_write > 0) {
> +		copy = min(words_to_write, WRITE_BUF_SIZE);
> +
> +		if (copy_from_user(tmp_buf, buf + copied * sizeof(u32),
> +				   copy * sizeof(u32))) {
> +			reset_ip_core(fifo);
> +			return -EFAULT;
> +		}
> +
> +		for (i = 0; i < copy; i++)
> +			iowrite32(tmp_buf[i], fifo->base_addr +
> +				  XLLF_TDFD_OFFSET);
> +
> +		copied += copy;
> +		words_to_write -= copy;
> +	}
> +
> +	/* write packet size to fifo */
> +	iowrite32(copied * sizeof(u32), fifo->base_addr + XLLF_TLR_OFFSET);
> +
> +	return (ssize_t)copied * sizeof(u32);
> +}
> +


> +/* read named property from the device tree */
> +static int get_dts_property(struct axis_fifo *fifo,
> +			    char *name, unsigned int *var)
> +{
> +	if (of_property_read_u32(fifo->dt_device->of_node,
> +				 name, var) < 0) {
> +		dev_err(fifo->dt_device,
> +			"couldn't read IP dts property '%s'", name);
> +		return -1;

Preserve the error code.  Plus it looks nicer:

	rc = of_property_read_u32(fifo->dt_device->of_node, name, var);
	if (rc) {
		dev_err(fifo->dt_device, "couldn't read IP dts property '%s'",
			name);
		return rc;
	}


> +	}
> +	dev_dbg(fifo->dt_device, "dts property '%s' = %u\n",
> +		name, *var);
> +
> +	return 0;
> +}
> +
> +static int axis_fifo_probe(struct platform_device *pdev)
> +{
> +	struct resource *r_irq; /* interrupt resources */
> +	struct resource *r_mem; /* IO mem resources */
> +	struct device *dev = &pdev->dev; /* OS device (from device tree) */
> +	struct axis_fifo *fifo = NULL;
> +
> +	char device_name[32];
> +
> +	int rc = 0; /* error return value */
> +
> +	/* IP properties from device tree */
> +	unsigned int rxd_tdata_width;
> +	unsigned int txc_tdata_width;
> +	unsigned int txd_tdata_width;
> +	unsigned int tdest_width;
> +	unsigned int tid_width;
> +	unsigned int tuser_width;
> +	unsigned int data_interface_type;
> +	unsigned int has_tdest;
> +	unsigned int has_tid;
> +	unsigned int has_tkeep;
> +	unsigned int has_tstrb;
> +	unsigned int has_tuser;
> +	unsigned int rx_fifo_depth;
> +	unsigned int rx_programmable_empty_threshold;
> +	unsigned int rx_programmable_full_threshold;
> +	unsigned int axi_id_width;
> +	unsigned int axi4_data_width;
> +	unsigned int select_xpm;
> +	unsigned int tx_fifo_depth;
> +	unsigned int tx_programmable_empty_threshold;
> +	unsigned int tx_programmable_full_threshold;
> +	unsigned int use_rx_cut_through;
> +	unsigned int use_rx_data;
> +	unsigned int use_tx_control;
> +	unsigned int use_tx_cut_through;
> +	unsigned int use_tx_data;
> +
> +	/* ----------------------------
> +	 *     init wrapper device
> +	 * ----------------------------
> +	 */
> +
> +	/* allocate device wrapper memory */
> +	fifo = devm_kmalloc(dev, sizeof(*fifo), GFP_KERNEL);
> +	if (!fifo)
> +		return -ENOMEM;
> +
> +	dev_set_drvdata(dev, fifo);
> +	fifo->dt_device = dev;
> +
> +	init_waitqueue_head(&fifo->read_queue);
> +	init_waitqueue_head(&fifo->write_queue);
> +
> +	dev_dbg(fifo->dt_device, "initialized queues\n");

This print doesn't tell you anything except that the function was
called.  Just remove it and use ftrace.

> +
> +	spin_lock_init(&fifo->read_queue_lock);
> +	spin_lock_init(&fifo->write_queue_lock);
> +
> +	dev_dbg(fifo->dt_device, "initialized spinlocks\n");

Delete.

> +
> +	/* ----------------------------
> +	 *   init device memory space
> +	 * ----------------------------
> +	 */
> +
> +	/* get iospace for the device */
> +	r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!r_mem) {
> +		dev_err(fifo->dt_device, "invalid address\n");
> +		rc = -ENODEV;
> +		goto err_initial;
> +	}
> +
> +	fifo->mem_start = r_mem->start;
> +	fifo->mem_end = r_mem->end;

Why not just save r_mem?

> +
> +	/* request physical memory */
> +	if (!request_mem_region(fifo->mem_start,
> +				fifo->mem_end -
> +				fifo->mem_start + 1,

				resource_size(r_mem),

> +				DRIVER_NAME)) {
> +		dev_err(fifo->dt_device,
> +			"couldn't lock memory region at %p\n",
> +			(void *)fifo->mem_start);
> +		rc = -EBUSY;
> +		goto err_initial;
> +	}
> +	dev_dbg(fifo->dt_device,
> +		"got memory location [0x%x - 0x%x]\n",
> +		fifo->mem_start, fifo->mem_end);
> +
> +	/* map physical memory to kernel virtual address space */
> +	fifo->base_addr = ioremap(fifo->mem_start, fifo->mem_end -
> +				  fifo->mem_start + 1);

	fifo->base_addr = ioremap(fifo->mem_start, resource_size(r_mem));

Fits on one line.

> +
> +	if (!fifo->base_addr) {
> +		dev_err(fifo->dt_device,
> +			"couldn't map physical memory\n");
> +		rc = -EIO;

For ioremap() failure the "rc = -ENOMEM;".

> +		goto err_mem;
> +	}
> +	dev_dbg(fifo->dt_device, "remapped memory to 0x%x\n",
> +		(unsigned int)fifo->base_addr);

Use %p.  Casting a pointer to (unsigned int) will generate a GCC
warning.  Plus casting is ugly.

> +
> +	/* create unique device name */
> +	snprintf(device_name, 32, DRIVER_NAME "_%x",
> +		 (unsigned int)fifo->mem_start);

Get rid of the magic 32 and the cast.

	snprintf(device_name, sizeof(device_name) "%s_%x",
		 DRIVER_NAME, fifo->mem_start);



> +
> +	dev_dbg(fifo->dt_device, "device name [%s]\n", device_name);
> +
> +	/* ----------------------------
> +	 *          init IP
> +	 * ----------------------------
> +	 */
> +
> +	/* retrieve device tree properties */
> +	if (get_dts_property(fifo, "xlnx,axi-str-rxd-tdata-width",
> +			     &rxd_tdata_width)) {
> +		rc = -EIO;
> +		goto err_mem;

After the ioremap() succeeds all the gotos should be goto unmap; until
we get to the next allocation.  Also preserve the error code:

	rc = get_dts_property(fifo, "xlnx,axi-str-rxd-tdata-width",
			       &rxd_tdata_width);
	if (rc)
		goto unmap;


> +	}
> +	if (get_dts_property(fifo, "xlnx,axi-str-txc-tdata-width",
> +			     &txc_tdata_width)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,axi-str-txd-tdata-width",
> +			     &txd_tdata_width)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,axis-tdest-width",
> +			     &tdest_width)) {

This will fit on one line:

	rc = get_dts_property(fifo, "xlnx,axis-tdest-width", &tdest_width);
	if (rc)
		goto unmap;


> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,axis-tid-width",
> +			     &tid_width)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,axis-tuser-width",
> +			     &tuser_width)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,data-interface-type",
> +			     &data_interface_type)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,has-axis-tdest",
> +			     &has_tdest)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,has-axis-tid",
> +			     &has_tid)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,has-axis-tkeep",
> +			     &has_tkeep)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,has-axis-tstrb",
> +			     &has_tstrb)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,has-axis-tuser",
> +			     &has_tuser)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,rx-fifo-depth",
> +			     &rx_fifo_depth)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,rx-fifo-pe-threshold",
> +			     &rx_programmable_empty_threshold)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,rx-fifo-pf-threshold",
> +			     &rx_programmable_full_threshold)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,s-axi-id-width",
> +			     &axi_id_width)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,s-axi4-data-width",
> +			     &axi4_data_width)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,select-xpm",
> +			     &select_xpm)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,tx-fifo-depth",
> +			     &tx_fifo_depth)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,tx-fifo-pe-threshold",
> +			     &tx_programmable_empty_threshold)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,tx-fifo-pf-threshold",
> +			     &tx_programmable_full_threshold)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,use-rx-cut-through",
> +			     &use_rx_cut_through)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,use-rx-data",
> +			     &use_rx_data)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,use-tx-ctrl",
> +			     &use_tx_control)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,use-tx-cut-through",
> +			     &use_tx_cut_through)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (get_dts_property(fifo, "xlnx,use-tx-data",
> +			     &use_tx_data)) {
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +
> +	/* check validity of device tree properties */
> +	if (rxd_tdata_width != 32) {
> +		dev_err(fifo->dt_device,
> +			"rxd_tdata_width width [%u] unsupported\n",
> +			rxd_tdata_width);
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (txd_tdata_width != 32) {
> +		dev_err(fifo->dt_device,
> +			"txd_tdata_width width [%u] unsupported\n",
> +			txd_tdata_width);
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (has_tdest) {
> +		dev_err(fifo->dt_device, "tdest not supported\n");
> +		rc = -EIO;
> +		goto err_mem;
> +	}

Just out of curiosity, what would happen if we remove this check?


> +	if (has_tid) {
> +		dev_err(fifo->dt_device, "tid not supported\n");
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (has_tkeep) {
> +		dev_err(fifo->dt_device, "tkeep not supported\n");
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (has_tstrb) {
> +		dev_err(fifo->dt_device, "tstrb not supported\n");
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (has_tuser) {
> +		dev_err(fifo->dt_device, "tuser not supported\n");
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (use_rx_cut_through) {
> +		dev_err(fifo->dt_device,
> +			"rx cut-through not supported\n");

Fits on one line:

		dev_err(fifo->dt_device, "rx cut-through not supported\n");


> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (use_tx_cut_through) {
> +		dev_err(fifo->dt_device,
> +			"tx cut-through not supported\n");
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	if (use_tx_control) {
> +		dev_err(fifo->dt_device,
> +			"tx control not supported\n");
> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +
> +	/* TODO
> +	 * these exist in the device tree but it's unclear what they do
> +	 * - select-xpm
> +	 * - data-interface-type
> +	 */
> +
> +	/* set device wrapper properties based on IP config */
> +	fifo->rx_fifo_depth = rx_fifo_depth;
> +	/* IP sets TDFV to fifo depth - 4 so we will do the same */
> +	fifo->tx_fifo_depth = tx_fifo_depth - 4;
> +	fifo->has_rx_fifo = use_rx_data;
> +	fifo->has_tx_fifo = use_tx_data;
> +
> +	reset_ip_core(fifo);
> +
> +	/* ----------------------------
> +	 *    init device interrupts
> +	 * ----------------------------
> +	 */
> +
> +	/* get IRQ resource */
> +	r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (!r_irq) {
> +		dev_err(fifo->dt_device,
> +			"no IRQ found at 0x%08x mapped to 0x%08x\n",
> +			(unsigned int __force)fifo->mem_start,
> +			(unsigned int __force)fifo->base_addr);

No need for __force.  Just get rid to the casts actually.

> +		rc = -EIO;
> +		goto err_mem;
> +	}
> +	dev_dbg(fifo->dt_device, "found IRQ\n");
> +
> +	/* request IRQ */
> +	fifo->irq = r_irq->start;
> +	rc = request_irq(fifo->irq, &axis_fifo_irq, 0,
> +			 DRIVER_NAME, fifo);
> +	if (rc) {
> +		dev_err(fifo->dt_device,
> +			"couldn't allocate interrupt %i\n",
> +			fifo->irq);
> +		rc = -EIO;

Just leave rc as is.

> +		goto err_mem;
> +	}
> +	dev_dbg(fifo->dt_device,
> +		"initialized IRQ %i\n",
> +		fifo->irq);

Fits on one line.

> +
> +	/* ----------------------------
> +	 *      init char device
> +	 * ----------------------------
> +	 */
> +
> +	/* allocate device number */
> +	if (alloc_chrdev_region(&fifo->devt, 0, 1, DRIVER_NAME) < 0) {
> +		dev_err(fifo->dt_device, "couldn't allocate dev_t\n");
> +		rc = -EIO;
> +		goto err_irq;
> +	}

	rc = alloc_chrdev_region(&fifo->devt, 0, 1, DRIVER_NAME);
	if (rc)
		goto err_irq;

Most of these functions have their own printks built in so there isn't
really a need to have a printk here.


> +	dev_dbg(fifo->dt_device,
> +		"allocated device number major %i minor %i\n",
> +		MAJOR(fifo->devt), MINOR(fifo->devt));
> +
> +	/* create driver file */
> +	fifo->device = NULL;

Delete this line.

> +	fifo->device = device_create(axis_fifo_driver_class, NULL, fifo->devt,
> +				     NULL, device_name);
> +	if (!fifo->device) {
> +		dev_err(fifo->dt_device,
> +			"couldn't create driver file\n");
> +		rc = -EIO;

rc = -ENOMEM;

> +		goto err_chrdev_region;
> +	}
> +	dev_set_drvdata(fifo->device, fifo);
> +	dev_dbg(fifo->dt_device, "created device file\n");

Just delete these debugging lines.  It's obviously to the point where
it's working and you can test it now.

> +
> +	/* create character device */
> +	cdev_init(&fifo->char_device, &fops);
> +	if (cdev_add(&fifo->char_device,
> +		     fifo->devt, 1) < 0) {
> +		dev_err(fifo->dt_device,
> +			"couldn't create character device\n");
> +		rc = -EIO;
> +		goto err_dev;
> +	}

Preserve the code.

> +	dev_dbg(fifo->dt_device, "created character device\n");
> +
> +	/* create sysfs entries */
> +	if (sysfs_create_group(&fifo->device->kobj,
> +			       &axis_fifo_attrs_group) < 0) {
> +		dev_err(fifo->dt_device,
> +			"couldn't register sysfs group\n");
> +		rc = -EIO;
> +		goto err_cdev;
> +	}
> +
> +	dev_info(fifo->dt_device,
> +		 "axis-fifo created at 0x%08x mapped to 0x%08x, irq=%i, major=%i, minor=%i\n",
> +		 (unsigned int __force)fifo->mem_start,
> +		 (unsigned int __force)fifo->base_addr,
> +		 fifo->irq, MAJOR(fifo->devt),
> +		 MINOR(fifo->devt));
> +
> +	return 0;
> +
> +err_cdev:
> +	cdev_del(&fifo->char_device);
> +err_dev:
> +	dev_set_drvdata(fifo->device, NULL);

This hopefully isn't required since we delete fifo->device on the
next line.

> +	device_destroy(axis_fifo_driver_class, fifo->devt);
> +err_chrdev_region:
> +	unregister_chrdev_region(fifo->devt, 1);
> +err_irq:
> +	free_irq(fifo->irq, fifo);
> +err_mem:
> +	release_mem_region(fifo->mem_start,
> +			   fifo->mem_end -
> +			   fifo->mem_start + 1);
> +err_initial:
> +	dev_set_drvdata(dev, NULL);
> +	return rc;
> +}
> +
> +static int axis_fifo_remove(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct axis_fifo *fifo = dev_get_drvdata(dev);
> +
> +	dev_info(dev, "removing\n");

Delete.  ftrace.

> +
> +	sysfs_remove_group(&fifo->device->kobj,
> +			   &axis_fifo_attrs_group);

One line:

	sysfs_remove_group(&fifo->device->kobj, &axis_fifo_attrs_group);


> +	cdev_del(&fifo->char_device);
> +	dev_set_drvdata(fifo->device, NULL);
> +	device_destroy(axis_fifo_driver_class, fifo->devt);
> +	unregister_chrdev_region(fifo->devt, 1);
> +	free_irq(fifo->irq, fifo);

Don't forget to do an iounmap() here as well.

> +	release_mem_region(fifo->mem_start,
> +			   fifo->mem_end -
> +			   fifo->mem_start + 1);
> +	dev_set_drvdata(dev, NULL);
> +	return 0;
> +}
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id axis_fifo_of_match[] = {
> +	{ .compatible = "xlnx,axi-fifo-mm-s-4.1", },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, axis_fifo_of_match);
> +#else
> +# define axis_fifo_of_match
> +#endif
> +
> +static struct platform_driver axis_fifo_driver = {
> +	.driver = {
> +		.name = DRIVER_NAME,
> +		.owner = THIS_MODULE,
> +		.of_match_table	= axis_fifo_of_match,
> +	},
> +	.probe		= axis_fifo_probe,
> +	.remove		= axis_fifo_remove,
> +};
> +
> +static int __init axis_fifo_init(void)
> +{
> +	printk(KERN_INFO "axis-fifo driver loaded with parameters read_timeout = %i, write_timeout = %i\n",
> +	       read_timeout, write_timeout);

Delete.  Or update to use pr_info() at least.

> +	axis_fifo_driver_class = class_create(THIS_MODULE, DRIVER_NAME);
> +	return platform_driver_register(&axis_fifo_driver);
> +}
> +
> +module_init(axis_fifo_init);
> +
> +static void __exit axis_fifo_exit(void)
> +{
> +	platform_driver_unregister(&axis_fifo_driver);
> +	class_destroy(axis_fifo_driver_class);
> +	printk(KERN_INFO "axis-fifo driver exit\n");

Delete.

> +}
> +

regards,
dan carpenter

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel



[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux