On Sun, 24 Feb 2013 16:59:23 +0300
Dan Carpenter <[email protected]> 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
[email protected]
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel