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