Re: More bugs in vme

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

 



On Sun, 24 Feb 2013 16:59:23 +0300
Dan Carpenter <dan.carpenter@xxxxxxxxxx> wrote:

> I've added Martyn and Manohar to the CC list again.

> Do you have lockdep enabled?

How do I do that?

>  Sometimes SYSRQ-T will still respond so you can get a trace.

I haven't been able to get the serial console working. This is U-Boot
based, and the last line is: "console [tty0] enabled, bootconsole
disabled". Then I use ssh to log in. But after the freeze, this is no longer possible.

> Or if you sent your reproducer program that would also help.  And
> which kernel are you using?

I've attached two files (some 300 lines). This is for kernel 3.8.0; I've inserted lots of messages all over the place for orientation. In vme_tsi148.c I disabled the window check as mentioned in my previous message. As suggested by Mr Welch, I started my own version of vme_user which for now just has a few more ioctls, giving access to functions which are mentioned in vme_api.txt. The only real change is, that in my version, vme_master_request is not done anymore in probe but based on an ioctl call, having a sister function allowing to remove the resources of that window.

I observed also:

- With my version of vme_user.c, I can perform a write using an ioctl
  call which yields vme_master_write(), or by lseek and write() calls.
  The freeze happens anyway, but with lseek() I say that a given offset
  of 8 will show up as 135168.

- I always thought that the card in slot 1 is the arbiter and, by
  default, the bus master, until some other card is assigned bus
  master. I would like to be sure, but I couldn't find any function I
  could inquire.

- The cards allow to adjust a dip switch to select automatic or manual
  geographic addressing, but in both cases, slot 0 is returned.

Thanks,

-- 
Christoph
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "vme_api.h"

int bus_num = 0;
int minor = 0;
uint16_t image = 0x0000;

static void
req_vme (void)
{
  char buf[80];

  sprintf (buf, "/dev/bus/vme%d/ctl", bus_num);
  if (!access (buf, F_OK))
    return;

  sprintf (buf, "modprobe vme_api bus=%d", bus_num);
  system (buf);

  sprintf (buf, "/dev/bus/vme%d/ctl", bus_num);
  if (access (buf, F_OK))
  {
    fprintf (stderr, "Can't load vme module\n");
    exit (1);
  }
}

static void
req_master (void)
{
  if (!access ("/dev/bus/vme0/m0", F_OK))
    return;
  else
  {
    char buf[80];
    struct vme_master_req vmq;
    int fd, err;

    sprintf (buf, "/dev/bus/vme%d/ctl", bus_num);
    fd = open (buf, O_RDWR);
    if (fd < 0)
    {
      perror ("open ctl");
      exit (1);
    }

    vmq.minor = minor;
    vmq.size = 0x10000;
    vmq.aspace = VME_A16;
    vmq.cycle = VME_SCT | VME_SUPER | VME_DATA;
    vmq.dwidth = VME_D16;

    err = ioctl (fd, VME_MASTER_REQ, &vmq);
    if (err)
    {
      perror ("master request");
      exit (1);
    }
    minor = vmq.minor;
  }
}

static int
cfg_master (void)
{
  struct vme_master vm;
  char buf[80];
  int fd, err;

  sprintf (buf, "/dev/bus/vme0/m%d", minor);
  fd = open (buf, O_RDWR);
  if (fd < 0)
  {
    perror (buf);
    exit (1);
  }

  vm.enable = 1;
  vm.vme_addr = 0xffff0000;
  vm.size = 0x10000;
  vm.aspace = VME_A16;
  vm.cycle = VME_SCT | VME_SUPER | VME_DATA;
  vm.dwidth = VME_D16;

  err = ioctl (fd, VME_MASTER_SET, &vm);
  if (err)
  {
    perror ("master set");
    exit (1);
  }

  return fd;
}

static void
do_write (int fd, char *pfx, off_t offset, uint8_t value)
{
  off_t ret;
  ssize_t wrt;

  if (offset == 8)
  {
    offset &= 0xff00;		/* clear lower bits */
    offset |= value;		/* set value */
  }
  else if (offset == 9)
  {
    offset &= 0x00ff;
    offset |= value >> 8;	/* set value */
    offset--;			/* align */
  }
  else
  {
    fprintf (stderr, "can't write at offset %ld\n", offset);
    exit (1);
  }

  ret = lseek (fd, offset, SEEK_SET);
  if (ret != offset)
  {
    printf ("%s-lseek %lu: ret=%lu, errno=%d: %s\n",
	    pfx, offset, ret, errno, strerror (errno));
    exit (1);
  }

  wrt = write (fd, &value, 2);		/* VME_D16 */
  if (wrt != 2)
  {
    printf ("%s-write %d: ret=%d, errno=%d: %s\n",
	    pfx, value, wrt, errno, strerror (errno));
  }
}

static void
data_out (int fd, uint8_t data)
{
  do_write (fd, "d", 0x08, data);
}

static void
addr_out (int fd, uint8_t addr)
{
  do_write (fd, "a", 0x09, addr);
  do_write (fd, "a", 0x09, addr | 0x20);
  do_write (fd, "a", 0x09, addr);
}


static void
output (int fd, uint8_t addr, uint8_t data)
{
  data_out (fd, data);
  addr_out (fd, addr);
}

int
main (int argc, char **argv)
{
  int fd;

  req_vme ();
  req_master ();
  fd = cfg_master ();

  while (1)
  {
    uint8_t addr, data;

    data = 1;
    for (addr = 0; addr < 32; addr++)
    {
      output (fd, addr, data);
      usleep (125000);
    }
    usleep (125000);
    data <<= 1;
    if (data == 0)
      data = 1;
  }

  /* not reached */

  close (fd);

  exit (0);
}
#ifndef VME_API_H
#define VME_API_H

#include <stdint.h>

/* VME Address Spaces */
#define VME_A16		0x1
#define VME_A24		0x2
#define VME_A32		0x4
#define VME_A64		0x8
#define VME_CRCSR	0x10
#define VME_USER1	0x20
#define VME_USER2	0x40
#define VME_USER3	0x80
#define VME_USER4	0x100

/* VME Cycle Types */
#define VME_SCT		0x1
#define VME_BLT		0x2
#define VME_MBLT	0x4
#define VME_2eVME	0x8
#define VME_2eSST	0x10
#define VME_2eSSTB	0x20
#define VME_2eSST160	0x100
#define VME_2eSST267	0x200
#define VME_2eSST320	0x400
#define VME_SUPER	0x1000
#define VME_USER	0x2000
#define VME_PROG	0x4000
#define VME_DATA	0x8000

/* VME Data Widths */
#define VME_D8		0x1
#define VME_D16		0x2
#define VME_D32		0x4
#define VME_D64		0x8

#define VME_IOC_MAGIC 0xAE

struct vme_master_req
{
  uint32_t minor;		/* output */
  uint64_t size;		/* always PCI_BUF_SIZE? */
  uint32_t aspace;		/* inputs: */
  uint32_t cycle;
  uint32_t dwidth;
};

struct vme_info
{
  int vme_slot_num;
  int board_responded;		/* Board responded */
  int system_controller;	/*  System controller flag */
  int vme_controller_id;	/*  Vendor/device ID of VME bridge */
  int vme_controller_rev;	/*  Revision of VME bridge */
  char os_name[8];		/*  Name of OS e.g. "Linux" */
  int vme_shared_data_valid;	/*  Validity of data struct */
  int vme_driver_rev;		/*  Revision of VME driver */
  unsigned int vme_addr_hi[8];	/* Address on VME bus */
  unsigned int vme_addr_lo[8];	/* Address on VME bus */
  unsigned int vme_size[8];	/* Size on VME bus */
  unsigned int vme_am[8];	/* Address modifier on VME bus */
};

struct vme_winfo
{
  uint32_t kern_buf;
  uint32_t pci_buf;
  uint32_t device;
  uint32_t resource;
  uint32_t users;
  uint32_t mapped;
  /* statistics not only for this window */
  uint32_t reads;
  uint32_t writes;
  uint32_t ioctls;
  uint32_t irqs;
  uint32_t berrs;
  uint32_t dmaErrors;
  uint32_t timeouts;
  uint32_t external;
};

/* VMEbus Master Window Configuration Structure */
struct vme_master
{
  int enable;			/* State of Window */
  uint64_t vme_addr;		/* Starting Address on the VMEbus */
  uint64_t size;		/* Window Size */
  uint32_t aspace;		/* Address Space */
  uint32_t cycle;		/* Cycle properties */
  uint32_t dwidth;		/* Maximum Data Width */
};

struct vme_xdata
{
  uint64_t addr;
  uint8_t buf[8];
  uint32_t len;
};

#define VME_INFO_GET		_IOR(VME_IOC_MAGIC, 10, struct vme_info)
#define VME_WINFO		_IOR(VME_IOC_MAGIC, 11, struct vme_winfo)
#define VME_MASTER_REQ		_IOWR(VME_IOC_MAGIC, 8, struct vme_master_req)
#define VME_MASTER_REL		_IOW(VME_IOC_MAGIC, 9, int)
#define VME_MASTER_GET		_IOR(VME_IOC_MAGIC, 3, struct vme_master)
#define VME_MASTER_SET		_IOW(VME_IOC_MAGIC, 4, struct vme_master)
#define VME_MASTER_PUT		_IOW(VME_IOC_MAGIC, 12, struct vme_xdata)

#endif
_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/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