From d7530a1e767b562c7e071f559d542c132d85fff7 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 00:58:01 +0200 Subject: [PATCH] ieee1394: fix cosmetic problem in speed probe If ieee1394.h::IEEE1394_SPEED_MAX is bigger than the actual speed of an 1394b host adapter and the speed to another 1394b node was probed, a bigger speed than actually used was kept in host->speed[n]. The only resulting problem so far was sbp2 displaying bogus values in the syslog, e.g. S3200 for actual S800 connections if IEEE1394_SPEED_MAX was S3200. But other high-level drivers which access this field could get into more trouble. (Eth1394 is the only other in-tree driver which does so. It seems it is not affected.) Nodemgr now clips this value according to the host adapter's link speed. A pointer expression in nodemgr_check_speed is also changed for clarity. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/nodemgr.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index d541b508a15..dfed2ed2ed9 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -71,7 +71,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr, u8 i, *speed, old_speed, good_speed; int ret; - speed = ci->host->speed + NODEID_TO_NODE(ci->nodeid); + speed = &(ci->host->speed[NODEID_TO_NODE(ci->nodeid)]); old_speed = *speed; good_speed = IEEE1394_SPEED_MAX + 1; @@ -1251,6 +1251,7 @@ static void nodemgr_node_scan_one(struct host_info *hi, octlet_t guid; struct csr1212_csr *csr; struct nodemgr_csr_info *ci; + u8 *speed; ci = kmalloc(sizeof(*ci), GFP_KERNEL); if (!ci) @@ -1259,8 +1260,12 @@ static void nodemgr_node_scan_one(struct host_info *hi, ci->host = host; ci->nodeid = nodeid; ci->generation = generation; - ci->speed_unverified = - host->speed[NODEID_TO_NODE(nodeid)] > IEEE1394_SPEED_100; + + /* Prepare for speed probe which occurs when reading the ROM */ + speed = &(host->speed[NODEID_TO_NODE(nodeid)]); + if (*speed > host->csr.lnk_spd) + *speed = host->csr.lnk_spd; + ci->speed_unverified = *speed > IEEE1394_SPEED_100; /* We need to detect when the ConfigROM's generation has changed, * so we only update the node's info when it needs to be. */ @@ -1300,8 +1305,6 @@ static void nodemgr_node_scan_one(struct host_info *hi, nodemgr_create_node(guid, csr, hi, nodeid, generation); else nodemgr_update_node(ne, csr, hi, nodeid, generation); - - return; } -- cgit v1.2.3 From 31a379e1067834868b8f1ce3e409392c42dc0f2b Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:01:58 -0400 Subject: [PATCH] ieee1394: sbp2: enable auto spin-up for Maxtor disks At least Maxtor OneTouch III require a "start stop unit" command after auto spin-down before the next access can proceed. This patch activates the responsible code in scsi_mod for all Maxtor SBP-2 disks. https://bugzilla.novell.com/show_bug.cgi?id=183011 Maybe that should be done for all SBP-2 disks, but better be cautious. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/sbp2.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index aaa74f293aa..b08755e2e68 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -2515,6 +2515,9 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev) sdev->skip_ms_page_8 = 1; if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) sdev->fix_capacity = 1; + if (scsi_id->ne->guid_vendor_id == 0x0010b9 && /* Maxtor's OUI */ + (sdev->type == TYPE_DISK || sdev->type == TYPE_RBC)) + sdev->allow_restart = 1; return 0; } -- cgit v1.2.3 From f0cbefe63c4347044fffebca24c03f3c6829f322 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:01:59 -0400 Subject: [PATCH] ieee1394: fix calculation of csr->expire This variant of calculate_expire() is more correct and easier to read. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/csr.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c index 149573db91c..ab0c80f61b9 100644 --- a/drivers/ieee1394/csr.c +++ b/drivers/ieee1394/csr.c @@ -17,11 +17,13 @@ * */ -#include +#include +#include #include #include #include #include +#include #include "csr1212.h" #include "ieee1394_types.h" @@ -149,31 +151,18 @@ static void host_reset(struct hpsb_host *host) /* * HI == seconds (bits 0:2) - * LO == fraction units of 1/8000 of a second, as per 1394 (bits 19:31) - * - * Convert to units and then to HZ, for comparison to jiffies. - * - * By default this will end up being 800 units, or 100ms (125usec per - * unit). + * LO == fractions of a second in units of 125usec (bits 19:31) * - * NOTE: The spec says 1/8000, but also says we can compute based on 1/8192 - * like CSR specifies. Should make our math less complex. + * Convert SPLIT_TIMEOUT to jiffies. + * The default and minimum as per 1394a-2000 clause 8.3.2.2.6 is 100ms. */ static inline void calculate_expire(struct csr_control *csr) { - unsigned long units; - - /* Take the seconds, and convert to units */ - units = (unsigned long)(csr->split_timeout_hi & 0x07) << 13; - - /* Add in the fractional units */ - units += (unsigned long)(csr->split_timeout_lo >> 19); - - /* Convert to jiffies */ - csr->expire = (unsigned long)(units * HZ) >> 13UL; + unsigned long usecs = + (csr->split_timeout_hi & 0x07) * USEC_PER_SEC + + (csr->split_timeout_lo >> 19) * 125L; - /* Just to keep from rounding low */ - csr->expire++; + csr->expire = usecs_to_jiffies(usecs > 100000L ? usecs : 100000L); HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%u", csr->expire, HZ); } -- cgit v1.2.3 From 433a87d528f685028b6f61fc3d7fae07ed915aa8 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:27 -0400 Subject: [PATCH] ieee1394: skip dummy loop in build_speed_map The last loop in ieee1394 core's speed calculation is not required unless ieee1394.h::IEEE1394_SPEED_MAX is changed from its current value of 3. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/ieee1394.h | 2 ++ drivers/ieee1394/ieee1394_core.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h index 936d776de00..d911abe3a35 100644 --- a/drivers/ieee1394/ieee1394.h +++ b/drivers/ieee1394/ieee1394.h @@ -77,6 +77,8 @@ extern const char *hpsb_speedto_str[]; #define SELFID_PORT_NCONN 0x1 #define SELFID_PORT_NONE 0x0 +#define SELFID_SPEED_UNKNOWN 0x3 /* 1394b PHY */ + #define PHYPACKET_LINKON 0x40000000 #define PHYPACKET_PHYCONFIG_R 0x00800000 #define PHYPACKET_PHYCONFIG_T 0x00400000 diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index f43739c5cab..559c477092f 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -355,10 +355,12 @@ static void build_speed_map(struct hpsb_host *host, int nodecount) } } +#if SELFID_SPEED_UNKNOWN != IEEE1394_SPEED_MAX /* assume maximum speed for 1394b PHYs, nodemgr will correct it */ for (n = 0; n < nodecount; n++) - if (speedcap[n] == 3) + if (speedcap[n] == SELFID_SPEED_UNKNOWN) speedcap[n] = IEEE1394_SPEED_MAX; +#endif } -- cgit v1.2.3 From 2b01b80b944b3abf623c8acc2b5537a85b5ebd3c Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:28 -0400 Subject: [PATCH] ieee1394: replace __inline__ by inline Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/ieee1394_types.h | 2 +- drivers/ieee1394/ohci1394.c | 5 +++-- drivers/ieee1394/sbp2.c | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h index 3165609ec1e..440d977031e 100644 --- a/drivers/ieee1394/ieee1394_types.h +++ b/drivers/ieee1394/ieee1394_types.h @@ -75,7 +75,7 @@ typedef u16 arm_length_t; #ifdef __BIG_ENDIAN -static __inline__ void *memcpy_le32(u32 *dest, const u32 *__src, size_t count) +static inline void *memcpy_le32(u32 *dest, const u32 *__src, size_t count) { void *tmp = dest; u32 *src = (u32 *)__src; diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index d4bad6704bb..2283005e303 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -2598,8 +2598,9 @@ static const int TCODE_SIZE[16] = {20, 0, 16, -1, 16, 20, 20, 0, * Determine the length of a packet in the buffer * Optimization suggested by Pascal Drolet */ -static __inline__ int packet_length(struct dma_rcv_ctx *d, int idx, quadlet_t *buf_ptr, - int offset, unsigned char tcode, int noswap) +static inline int packet_length(struct dma_rcv_ctx *d, int idx, + quadlet_t *buf_ptr, int offset, + unsigned char tcode, int noswap) { int length = -1; diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index b08755e2e68..baa063c9e6e 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -356,7 +356,7 @@ static const struct { /* * Converts a buffer from be32 to cpu byte ordering. Length is in bytes. */ -static __inline__ void sbp2util_be32_to_cpu_buffer(void *buffer, int length) +static inline void sbp2util_be32_to_cpu_buffer(void *buffer, int length) { u32 *temp = buffer; @@ -369,7 +369,7 @@ static __inline__ void sbp2util_be32_to_cpu_buffer(void *buffer, int length) /* * Converts a buffer from cpu to be32 byte ordering. Length is in bytes. */ -static __inline__ void sbp2util_cpu_to_be32_buffer(void *buffer, int length) +static inline void sbp2util_cpu_to_be32_buffer(void *buffer, int length) { u32 *temp = buffer; -- cgit v1.2.3 From e1d118f16dca0f54faba3e8dd5b6adbbf7ac68c8 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:28 -0400 Subject: [PATCH] ieee1394: coding style and comment fixes in midlayer header files Adjust tabulators, line wraps, empty lines, and comment style. Update comments in ieee1394_transactions.h and highlevel.h. Fix typo in comment in csr.h. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/csr.h | 98 +++++----- drivers/ieee1394/dma.h | 81 +++++--- drivers/ieee1394/highlevel.h | 197 ++++++++++--------- drivers/ieee1394/hosts.h | 15 +- drivers/ieee1394/ieee1394-ioctl.h | 9 +- drivers/ieee1394/ieee1394.h | 314 +++++++++++++++---------------- drivers/ieee1394/ieee1394_core.h | 17 +- drivers/ieee1394/ieee1394_transactions.h | 32 ++-- drivers/ieee1394/ieee1394_types.h | 31 ++- drivers/ieee1394/iso.h | 80 ++++---- drivers/ieee1394/nodemgr.h | 16 +- 11 files changed, 449 insertions(+), 441 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/csr.h b/drivers/ieee1394/csr.h index ea9aa4f53ab..0655596f25d 100644 --- a/drivers/ieee1394/csr.h +++ b/drivers/ieee1394/csr.h @@ -8,68 +8,68 @@ #include "csr1212.h" -#define CSR_REGISTER_BASE 0xfffff0000000ULL +#define CSR_REGISTER_BASE 0xfffff0000000ULL /* register offsets relative to CSR_REGISTER_BASE */ -#define CSR_STATE_CLEAR 0x0 -#define CSR_STATE_SET 0x4 -#define CSR_NODE_IDS 0x8 -#define CSR_RESET_START 0xc -#define CSR_SPLIT_TIMEOUT_HI 0x18 -#define CSR_SPLIT_TIMEOUT_LO 0x1c -#define CSR_CYCLE_TIME 0x200 -#define CSR_BUS_TIME 0x204 -#define CSR_BUSY_TIMEOUT 0x210 -#define CSR_BUS_MANAGER_ID 0x21c -#define CSR_BANDWIDTH_AVAILABLE 0x220 -#define CSR_CHANNELS_AVAILABLE 0x224 -#define CSR_CHANNELS_AVAILABLE_HI 0x224 -#define CSR_CHANNELS_AVAILABLE_LO 0x228 -#define CSR_BROADCAST_CHANNEL 0x234 -#define CSR_CONFIG_ROM 0x400 -#define CSR_CONFIG_ROM_END 0x800 -#define CSR_FCP_COMMAND 0xB00 -#define CSR_FCP_RESPONSE 0xD00 -#define CSR_FCP_END 0xF00 -#define CSR_TOPOLOGY_MAP 0x1000 -#define CSR_TOPOLOGY_MAP_END 0x1400 -#define CSR_SPEED_MAP 0x2000 -#define CSR_SPEED_MAP_END 0x3000 +#define CSR_STATE_CLEAR 0x0 +#define CSR_STATE_SET 0x4 +#define CSR_NODE_IDS 0x8 +#define CSR_RESET_START 0xc +#define CSR_SPLIT_TIMEOUT_HI 0x18 +#define CSR_SPLIT_TIMEOUT_LO 0x1c +#define CSR_CYCLE_TIME 0x200 +#define CSR_BUS_TIME 0x204 +#define CSR_BUSY_TIMEOUT 0x210 +#define CSR_BUS_MANAGER_ID 0x21c +#define CSR_BANDWIDTH_AVAILABLE 0x220 +#define CSR_CHANNELS_AVAILABLE 0x224 +#define CSR_CHANNELS_AVAILABLE_HI 0x224 +#define CSR_CHANNELS_AVAILABLE_LO 0x228 +#define CSR_BROADCAST_CHANNEL 0x234 +#define CSR_CONFIG_ROM 0x400 +#define CSR_CONFIG_ROM_END 0x800 +#define CSR_FCP_COMMAND 0xB00 +#define CSR_FCP_RESPONSE 0xD00 +#define CSR_FCP_END 0xF00 +#define CSR_TOPOLOGY_MAP 0x1000 +#define CSR_TOPOLOGY_MAP_END 0x1400 +#define CSR_SPEED_MAP 0x2000 +#define CSR_SPEED_MAP_END 0x3000 /* IEEE 1394 bus specific Configuration ROM Key IDs */ #define IEEE1394_KV_ID_POWER_REQUIREMENTS (0x30) -/* IEEE 1394 Bus Inforamation Block specifics */ +/* IEEE 1394 Bus Information Block specifics */ #define CSR_BUS_INFO_SIZE (5 * sizeof(quadlet_t)) -#define CSR_IRMC_SHIFT 31 -#define CSR_CMC_SHIFT 30 -#define CSR_ISC_SHIFT 29 -#define CSR_BMC_SHIFT 28 -#define CSR_PMC_SHIFT 27 -#define CSR_CYC_CLK_ACC_SHIFT 16 -#define CSR_MAX_REC_SHIFT 12 -#define CSR_MAX_ROM_SHIFT 8 -#define CSR_GENERATION_SHIFT 4 +#define CSR_IRMC_SHIFT 31 +#define CSR_CMC_SHIFT 30 +#define CSR_ISC_SHIFT 29 +#define CSR_BMC_SHIFT 28 +#define CSR_PMC_SHIFT 27 +#define CSR_CYC_CLK_ACC_SHIFT 16 +#define CSR_MAX_REC_SHIFT 12 +#define CSR_MAX_ROM_SHIFT 8 +#define CSR_GENERATION_SHIFT 4 #define CSR_SET_BUS_INFO_GENERATION(csr, gen) \ ((csr)->bus_info_data[2] = \ cpu_to_be32((be32_to_cpu((csr)->bus_info_data[2]) & \ - ~(0xf << CSR_GENERATION_SHIFT)) | \ + ~(0xf << CSR_GENERATION_SHIFT)) | \ (gen) << CSR_GENERATION_SHIFT)) struct csr_control { - spinlock_t lock; - - quadlet_t state; - quadlet_t node_ids; - quadlet_t split_timeout_hi, split_timeout_lo; - unsigned long expire; // Calculated from split_timeout - quadlet_t cycle_time; - quadlet_t bus_time; - quadlet_t bus_manager_id; - quadlet_t bandwidth_available; - quadlet_t channels_available_hi, channels_available_lo; + spinlock_t lock; + + quadlet_t state; + quadlet_t node_ids; + quadlet_t split_timeout_hi, split_timeout_lo; + unsigned long expire; /* Calculated from split_timeout */ + quadlet_t cycle_time; + quadlet_t bus_time; + quadlet_t bus_manager_id; + quadlet_t bandwidth_available; + quadlet_t channels_available_hi, channels_available_lo; quadlet_t broadcast_channel; /* Bus Info */ @@ -84,8 +84,8 @@ struct csr_control { struct csr1212_csr *rom; - quadlet_t topology_map[256]; - quadlet_t speed_map[1024]; + quadlet_t topology_map[256]; + quadlet_t speed_map[1024]; }; extern struct csr1212_bus_ops csr_bus_ops; diff --git a/drivers/ieee1394/dma.h b/drivers/ieee1394/dma.h index 061550a6fb9..b0f0885c455 100644 --- a/drivers/ieee1394/dma.h +++ b/drivers/ieee1394/dma.h @@ -13,66 +13,85 @@ #include #include -/* struct dma_prog_region - - a small, physically-contiguous DMA buffer with random-access, - synchronous usage characteristics -*/ - +/** + * struct dma_prog_region - small contiguous DMA buffer + * @kvirt: kernel virtual address + * @dev: PCI device + * @n_pages: number of kernel pages + * @bus_addr: base bus address + * + * a small, physically contiguous DMA buffer with random-access, synchronous + * usage characteristics + */ struct dma_prog_region { - unsigned char *kvirt; /* kernel virtual address */ - struct pci_dev *dev; /* PCI device */ - unsigned int n_pages; /* # of kernel pages */ - dma_addr_t bus_addr; /* base bus address */ + unsigned char *kvirt; + struct pci_dev *dev; + unsigned int n_pages; + dma_addr_t bus_addr; }; /* clear out all fields but do not allocate any memory */ void dma_prog_region_init(struct dma_prog_region *prog); -int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev); +int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, + struct pci_dev *dev); void dma_prog_region_free(struct dma_prog_region *prog); -static inline dma_addr_t dma_prog_region_offset_to_bus(struct dma_prog_region *prog, unsigned long offset) +static inline dma_addr_t dma_prog_region_offset_to_bus( + struct dma_prog_region *prog, unsigned long offset) { return prog->bus_addr + offset; } -/* struct dma_region - - a large, non-physically-contiguous DMA buffer with streaming, - asynchronous usage characteristics -*/ - +/** + * struct dma_region - large non-contiguous DMA buffer + * @virt: kernel virtual address + * @dev: PCI device + * @n_pages: number of kernel pages + * @n_dma_pages: number of IOMMU pages + * @sglist: IOMMU mapping + * @direction: PCI_DMA_TODEVICE, etc. + * + * a large, non-physically-contiguous DMA buffer with streaming, asynchronous + * usage characteristics + */ struct dma_region { - unsigned char *kvirt; /* kernel virtual address */ - struct pci_dev *dev; /* PCI device */ - unsigned int n_pages; /* # of kernel pages */ - unsigned int n_dma_pages; /* # of IOMMU pages */ - struct scatterlist *sglist; /* IOMMU mapping */ - int direction; /* PCI_DMA_TODEVICE, etc */ + unsigned char *kvirt; + struct pci_dev *dev; + unsigned int n_pages; + unsigned int n_dma_pages; + struct scatterlist *sglist; + int direction; }; /* clear out all fields but do not allocate anything */ void dma_region_init(struct dma_region *dma); /* allocate the buffer and map it to the IOMMU */ -int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_dev *dev, int direction); +int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, + struct pci_dev *dev, int direction); /* unmap and free the buffer */ void dma_region_free(struct dma_region *dma); /* sync the CPU's view of the buffer */ -void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset, unsigned long len); +void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset, + unsigned long len); + /* sync the IO bus' view of the buffer */ -void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset, unsigned long len); +void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset, + unsigned long len); /* map the buffer into a user space process */ -int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma); +int dma_region_mmap(struct dma_region *dma, struct file *file, + struct vm_area_struct *vma); /* macro to index into a DMA region (or dma_prog_region) */ -#define dma_region_i(_dma, _type, _index) ( ((_type*) ((_dma)->kvirt)) + (_index) ) +#define dma_region_i(_dma, _type, _index) \ + ( ((_type*) ((_dma)->kvirt)) + (_index) ) /* return the DMA bus address of the byte with the given offset - relative to the beginning of the dma_region */ -dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset); + * relative to the beginning of the dma_region */ +dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, + unsigned long offset); #endif /* IEEE1394_DMA_H */ diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h index e119fb87e5b..134bb6c3ead 100644 --- a/drivers/ieee1394/highlevel.h +++ b/drivers/ieee1394/highlevel.h @@ -1,60 +1,51 @@ - #ifndef IEEE1394_HIGHLEVEL_H #define IEEE1394_HIGHLEVEL_H - +/* internal to ieee1394 core */ struct hpsb_address_serve { - struct list_head host_list; /* per host list */ - - struct list_head hl_list; /* hpsb_highlevel list */ - - struct hpsb_address_ops *op; - + struct list_head host_list; /* per host list */ + struct list_head hl_list; /* hpsb_highlevel list */ + struct hpsb_address_ops *op; struct hpsb_host *host; - - /* first address handled and first address behind, quadlet aligned */ - u64 start, end; + u64 start; /* first address handled, quadlet aligned */ + u64 end; /* first address behind, quadlet aligned */ }; - -/* - * The above structs are internal to highlevel driver handling. Only the - * following structures are of interest to actual highlevel drivers. - */ +/* Only the following structures are of interest to actual highlevel drivers. */ struct hpsb_highlevel { struct module *owner; const char *name; - /* Any of the following pointers can legally be NULL, except for - * iso_receive which can only be NULL when you don't request - * channels. */ + /* Any of the following pointers can legally be NULL, except for + * iso_receive which can only be NULL when you don't request + * channels. */ - /* New host initialized. Will also be called during - * hpsb_register_highlevel for all hosts already installed. */ - void (*add_host) (struct hpsb_host *host); + /* New host initialized. Will also be called during + * hpsb_register_highlevel for all hosts already installed. */ + void (*add_host)(struct hpsb_host *host); - /* Host about to be removed. Will also be called during - * hpsb_unregister_highlevel once for each host. */ - void (*remove_host) (struct hpsb_host *host); + /* Host about to be removed. Will also be called during + * hpsb_unregister_highlevel once for each host. */ + void (*remove_host)(struct hpsb_host *host); - /* Host experienced bus reset with possible configuration changes. + /* Host experienced bus reset with possible configuration changes. * Note that this one may occur during interrupt/bottom half handling. * You can not expect to be able to do stock hpsb_reads. */ - void (*host_reset) (struct hpsb_host *host); + void (*host_reset)(struct hpsb_host *host); - /* An isochronous packet was received. Channel contains the channel - * number for your convenience, it is also contained in the included - * packet header (first quadlet, CRCs are missing). You may get called - * for channel/host combinations you did not request. */ - void (*iso_receive) (struct hpsb_host *host, int channel, - quadlet_t *data, size_t length); + /* An isochronous packet was received. Channel contains the channel + * number for your convenience, it is also contained in the included + * packet header (first quadlet, CRCs are missing). You may get called + * for channel/host combinations you did not request. */ + void (*iso_receive)(struct hpsb_host *host, int channel, + quadlet_t *data, size_t length); - /* A write request was received on either the FCP_COMMAND (direction = - * 0) or the FCP_RESPONSE (direction = 1) register. The cts arg - * contains the cts field (first byte of data). */ - void (*fcp_request) (struct hpsb_host *host, int nodeid, int direction, - int cts, u8 *data, size_t length); + /* A write request was received on either the FCP_COMMAND (direction = + * 0) or the FCP_RESPONSE (direction = 1) register. The cts arg + * contains the cts field (first byte of data). */ + void (*fcp_request)(struct hpsb_host *host, int nodeid, int direction, + int cts, u8 *data, size_t length); /* These are initialized by the subsystem when the * hpsb_higlevel is registered. */ @@ -67,61 +58,62 @@ struct hpsb_highlevel { }; struct hpsb_address_ops { - /* - * Null function pointers will make the respective operation complete - * with RCODE_TYPE_ERROR. Makes for easy to implement read-only - * registers (just leave everything but read NULL). - * - * All functions shall return appropriate IEEE 1394 rcodes. - */ - - /* These functions have to implement block reads for themselves. */ - /* These functions either return a response code - or a negative number. In the first case a response will be generated; in the - later case, no response will be sent and the driver, that handled the request - will send the response itself - */ - int (*read) (struct hpsb_host *host, int nodeid, quadlet_t *buffer, - u64 addr, size_t length, u16 flags); - int (*write) (struct hpsb_host *host, int nodeid, int destid, - quadlet_t *data, u64 addr, size_t length, u16 flags); - - /* Lock transactions: write results of ext_tcode operation into - * *store. */ - int (*lock) (struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags); - int (*lock64) (struct hpsb_host *host, int nodeid, octlet_t *store, - u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags); + /* + * Null function pointers will make the respective operation complete + * with RCODE_TYPE_ERROR. Makes for easy to implement read-only + * registers (just leave everything but read NULL). + * + * All functions shall return appropriate IEEE 1394 rcodes. + */ + + /* These functions have to implement block reads for themselves. + * + * These functions either return a response code or a negative number. + * In the first case a response will be generated. In the latter case, + * no response will be sent and the driver which handled the request + * will send the response itself. */ + int (*read)(struct hpsb_host *host, int nodeid, quadlet_t *buffer, + u64 addr, size_t length, u16 flags); + int (*write)(struct hpsb_host *host, int nodeid, int destid, + quadlet_t *data, u64 addr, size_t length, u16 flags); + + /* Lock transactions: write results of ext_tcode operation into + * *store. */ + int (*lock)(struct hpsb_host *host, int nodeid, quadlet_t *store, + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, + u16 flags); + int (*lock64)(struct hpsb_host *host, int nodeid, octlet_t *store, + u64 addr, octlet_t data, octlet_t arg, int ext_tcode, + u16 flags); }; - void highlevel_add_host(struct hpsb_host *host); void highlevel_remove_host(struct hpsb_host *host); void highlevel_host_reset(struct hpsb_host *host); - -/* these functions are called to handle transactions. They are called, when - a packet arrives. The flags argument contains the second word of the first header - quadlet of the incoming packet (containing transaction label, retry code, - transaction code and priority). These functions either return a response code - or a negative number. In the first case a response will be generated; in the - later case, no response will be sent and the driver, that handled the request - will send the response itself. -*/ -int highlevel_read(struct hpsb_host *host, int nodeid, void *data, - u64 addr, unsigned int length, u16 flags); -int highlevel_write(struct hpsb_host *host, int nodeid, int destid, - void *data, u64 addr, unsigned int length, u16 flags); +/* + * These functions are called to handle transactions. They are called when a + * packet arrives. The flags argument contains the second word of the first + * header quadlet of the incoming packet (containing transaction label, retry + * code, transaction code and priority). These functions either return a + * response code or a negative number. In the first case a response will be + * generated. In the latter case, no response will be sent and the driver which + * handled the request will send the response itself. + */ +int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr, + unsigned int length, u16 flags); +int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data, + u64 addr, unsigned int length, u16 flags); int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags); + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, + u16 flags); int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store, - u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags); + u64 addr, octlet_t data, octlet_t arg, int ext_tcode, + u16 flags); -void highlevel_iso_receive(struct hpsb_host *host, void *data, - size_t length); +void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length); void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, - void *data, size_t length); - + void *data, size_t length); /* * Register highlevel driver. The name pointer has to stay valid at all times @@ -132,13 +124,15 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl); /* * Register handlers for host address spaces. Start and end are 48 bit pointers - * and have to be quadlet aligned (end points to the first address behind the - * handled addresses. This function can be called multiple times for a single - * hpsb_highlevel to implement sparse register sets. The requested region must - * not overlap any previously allocated region, otherwise registering will fail. + * and have to be quadlet aligned. Argument "end" points to the first address + * behind the handled addresses. This function can be called multiple times for + * a single hpsb_highlevel to implement sparse register sets. The requested + * region must not overlap any previously allocated region, otherwise + * registering will fail. * - * It returns true for successful allocation. There is no unregister function, - * all address spaces are deallocated together with the hpsb_highlevel. + * It returns true for successful allocation. Address spaces can be + * unregistered with hpsb_unregister_addrspace. All remaining address spaces + * are automatically deallocated together with the hpsb_highlevel. */ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, @@ -146,20 +140,18 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, u64 size, u64 alignment, u64 start, u64 end); int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, - struct hpsb_address_ops *ops, u64 start, u64 end); - + struct hpsb_address_ops *ops, u64 start, u64 end); int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, - u64 start); + u64 start); /* * Enable or disable receving a certain isochronous channel through the * iso_receive op. */ int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, - unsigned int channel); + unsigned int channel); void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, - unsigned int channel); - + unsigned int channel); /* Retrieve a hostinfo pointer bound to this driver/host */ void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host); @@ -172,19 +164,24 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host); /* Set an alternate lookup key for the hostinfo bound to this driver/host */ -void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned long key); +void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, + unsigned long key); -/* Retrieve the alternate lookup key for the hostinfo bound to this driver/host */ -unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host); +/* Retrieve the alternate lookup key for the hostinfo bound to this + * driver/host */ +unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl, + struct hpsb_host *host); /* Retrieve a hostinfo pointer bound to this driver using its alternate key */ void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key); /* Set the hostinfo pointer to something useful. Usually follows a call to * hpsb_create_hostinfo, where the size is 0. */ -int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, void *data); +int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, + void *data); /* Retrieve hpsb_host using a highlevel handle and a key */ -struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key); +struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, + unsigned long key); #endif /* IEEE1394_HIGHLEVEL_H */ diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index 9ad4b246307..857d7d80bc8 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h @@ -112,7 +112,7 @@ enum devctl_cmd { enum isoctl_cmd { /* rawiso API - see iso.h for the meanings of these commands - (they correspond exactly to the hpsb_iso_* API functions) + * (they correspond exactly to the hpsb_iso_* API functions) * INIT = allocate resources * START = begin transmission/reception * STOP = halt transmission/reception @@ -160,7 +160,8 @@ struct hpsb_host_driver { /* The hardware driver may optionally support a function that is used * to set the hardware ConfigROM if the hardware supports handling * reads to the ConfigROM on its own. */ - void (*set_hw_config_rom) (struct hpsb_host *host, quadlet_t *config_rom); + void (*set_hw_config_rom)(struct hpsb_host *host, + quadlet_t *config_rom); /* This function shall implement packet transmission based on * packet->type. It shall CRC both parts of the packet (unless @@ -170,20 +171,21 @@ struct hpsb_host_driver { * called. Return 0 on success, negative errno on failure. * NOTE: The function must be callable in interrupt context. */ - int (*transmit_packet) (struct hpsb_host *host, - struct hpsb_packet *packet); + int (*transmit_packet)(struct hpsb_host *host, + struct hpsb_packet *packet); /* This function requests miscellanous services from the driver, see * above for command codes and expected actions. Return -1 for unknown * command, though that should never happen. */ - int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg); + int (*devctl)(struct hpsb_host *host, enum devctl_cmd command, int arg); /* ISO transmission/reception functions. Return 0 on success, -1 * (or -EXXX errno code) on failure. If the low-level driver does not * support the new ISO API, set isoctl to NULL. */ - int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg); + int (*isoctl)(struct hpsb_iso *iso, enum isoctl_cmd command, + unsigned long arg); /* This function is mainly to redirect local CSR reads/locks to the iso * management registers (bus manager id, bandwidth available, channels @@ -196,7 +198,6 @@ struct hpsb_host_driver { quadlet_t data, quadlet_t compare); }; - struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, struct device *dev); int hpsb_add_host(struct hpsb_host *host); diff --git a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h index 15670398634..8f207508ed1 100644 --- a/drivers/ieee1394/ieee1394-ioctl.h +++ b/drivers/ieee1394/ieee1394-ioctl.h @@ -1,5 +1,7 @@ -/* Base file for all ieee1394 ioctl's. Linux-1394 has allocated base '#' - * with a range of 0x00-0x3f. */ +/* + * Base file for all ieee1394 ioctl's. + * Linux-1394 has allocated base '#' with a range of 0x00-0x3f. + */ #ifndef __IEEE1394_IOCTL_H #define __IEEE1394_IOCTL_H @@ -96,8 +98,7 @@ _IOW ('#', 0x27, struct raw1394_iso_packets) #define RAW1394_IOC_ISO_XMIT_SYNC \ _IO ('#', 0x28) -#define RAW1394_IOC_ISO_RECV_FLUSH \ +#define RAW1394_IOC_ISO_RECV_FLUSH \ _IO ('#', 0x29) - #endif /* __IEEE1394_IOCTL_H */ diff --git a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h index d911abe3a35..40492074c01 100644 --- a/drivers/ieee1394/ieee1394.h +++ b/drivers/ieee1394/ieee1394.h @@ -5,77 +5,76 @@ #ifndef _IEEE1394_IEEE1394_H #define _IEEE1394_IEEE1394_H -#define TCODE_WRITEQ 0x0 -#define TCODE_WRITEB 0x1 -#define TCODE_WRITE_RESPONSE 0x2 -#define TCODE_READQ 0x4 -#define TCODE_READB 0x5 -#define TCODE_READQ_RESPONSE 0x6 -#define TCODE_READB_RESPONSE 0x7 -#define TCODE_CYCLE_START 0x8 -#define TCODE_LOCK_REQUEST 0x9 -#define TCODE_ISO_DATA 0xa -#define TCODE_STREAM_DATA 0xa -#define TCODE_LOCK_RESPONSE 0xb - -#define RCODE_COMPLETE 0x0 -#define RCODE_CONFLICT_ERROR 0x4 -#define RCODE_DATA_ERROR 0x5 -#define RCODE_TYPE_ERROR 0x6 -#define RCODE_ADDRESS_ERROR 0x7 - -#define EXTCODE_MASK_SWAP 0x1 -#define EXTCODE_COMPARE_SWAP 0x2 -#define EXTCODE_FETCH_ADD 0x3 -#define EXTCODE_LITTLE_ADD 0x4 -#define EXTCODE_BOUNDED_ADD 0x5 -#define EXTCODE_WRAP_ADD 0x6 - -#define ACK_COMPLETE 0x1 -#define ACK_PENDING 0x2 -#define ACK_BUSY_X 0x4 -#define ACK_BUSY_A 0x5 -#define ACK_BUSY_B 0x6 -#define ACK_TARDY 0xb -#define ACK_CONFLICT_ERROR 0xc -#define ACK_DATA_ERROR 0xd -#define ACK_TYPE_ERROR 0xe -#define ACK_ADDRESS_ERROR 0xf +#define TCODE_WRITEQ 0x0 +#define TCODE_WRITEB 0x1 +#define TCODE_WRITE_RESPONSE 0x2 +#define TCODE_READQ 0x4 +#define TCODE_READB 0x5 +#define TCODE_READQ_RESPONSE 0x6 +#define TCODE_READB_RESPONSE 0x7 +#define TCODE_CYCLE_START 0x8 +#define TCODE_LOCK_REQUEST 0x9 +#define TCODE_ISO_DATA 0xa +#define TCODE_STREAM_DATA 0xa +#define TCODE_LOCK_RESPONSE 0xb + +#define RCODE_COMPLETE 0x0 +#define RCODE_CONFLICT_ERROR 0x4 +#define RCODE_DATA_ERROR 0x5 +#define RCODE_TYPE_ERROR 0x6 +#define RCODE_ADDRESS_ERROR 0x7 + +#define EXTCODE_MASK_SWAP 0x1 +#define EXTCODE_COMPARE_SWAP 0x2 +#define EXTCODE_FETCH_ADD 0x3 +#define EXTCODE_LITTLE_ADD 0x4 +#define EXTCODE_BOUNDED_ADD 0x5 +#define EXTCODE_WRAP_ADD 0x6 + +#define ACK_COMPLETE 0x1 +#define ACK_PENDING 0x2 +#define ACK_BUSY_X 0x4 +#define ACK_BUSY_A 0x5 +#define ACK_BUSY_B 0x6 +#define ACK_TARDY 0xb +#define ACK_CONFLICT_ERROR 0xc +#define ACK_DATA_ERROR 0xd +#define ACK_TYPE_ERROR 0xe +#define ACK_ADDRESS_ERROR 0xf /* Non-standard "ACK codes" for internal use */ -#define ACKX_NONE (-1) -#define ACKX_SEND_ERROR (-2) -#define ACKX_ABORTED (-3) -#define ACKX_TIMEOUT (-4) - - -#define IEEE1394_SPEED_100 0x00 -#define IEEE1394_SPEED_200 0x01 -#define IEEE1394_SPEED_400 0x02 -#define IEEE1394_SPEED_800 0x03 -#define IEEE1394_SPEED_1600 0x04 -#define IEEE1394_SPEED_3200 0x05 +#define ACKX_NONE (-1) +#define ACKX_SEND_ERROR (-2) +#define ACKX_ABORTED (-3) +#define ACKX_TIMEOUT (-4) + +#define IEEE1394_SPEED_100 0x00 +#define IEEE1394_SPEED_200 0x01 +#define IEEE1394_SPEED_400 0x02 +#define IEEE1394_SPEED_800 0x03 +#define IEEE1394_SPEED_1600 0x04 +#define IEEE1394_SPEED_3200 0x05 + /* The current highest tested speed supported by the subsystem */ -#define IEEE1394_SPEED_MAX IEEE1394_SPEED_800 +#define IEEE1394_SPEED_MAX IEEE1394_SPEED_800 /* Maps speed values above to a string representation */ extern const char *hpsb_speedto_str[]; - /* 1394a cable PHY packets */ -#define SELFID_PWRCL_NO_POWER 0x0 -#define SELFID_PWRCL_PROVIDE_15W 0x1 -#define SELFID_PWRCL_PROVIDE_30W 0x2 -#define SELFID_PWRCL_PROVIDE_45W 0x3 -#define SELFID_PWRCL_USE_1W 0x4 -#define SELFID_PWRCL_USE_3W 0x5 -#define SELFID_PWRCL_USE_6W 0x6 -#define SELFID_PWRCL_USE_10W 0x7 - -#define SELFID_PORT_CHILD 0x3 -#define SELFID_PORT_PARENT 0x2 -#define SELFID_PORT_NCONN 0x1 -#define SELFID_PORT_NONE 0x0 +#define SELFID_PWRCL_NO_POWER 0x0 +#define SELFID_PWRCL_PROVIDE_15W 0x1 +#define SELFID_PWRCL_PROVIDE_30W 0x2 +#define SELFID_PWRCL_PROVIDE_45W 0x3 +#define SELFID_PWRCL_USE_1W 0x4 +#define SELFID_PWRCL_USE_3W 0x5 +#define SELFID_PWRCL_USE_6W 0x6 +#define SELFID_PWRCL_USE_10W 0x7 + +#define SELFID_PORT_CHILD 0x3 +#define SELFID_PORT_PARENT 0x2 +#define SELFID_PORT_NCONN 0x1 +#define SELFID_PORT_NONE 0x0 #define SELFID_SPEED_UNKNOWN 0x3 /* 1394b PHY */ @@ -93,76 +92,76 @@ extern const char *hpsb_speedto_str[]; #define EXTPHYPACKET_TYPEMASK 0xC0FC0000 -#define PHYPACKET_PORT_SHIFT 24 -#define PHYPACKET_GAPCOUNT_SHIFT 16 +#define PHYPACKET_PORT_SHIFT 24 +#define PHYPACKET_GAPCOUNT_SHIFT 16 /* 1394a PHY register map bitmasks */ -#define PHY_00_PHYSICAL_ID 0xFC -#define PHY_00_R 0x02 /* Root */ -#define PHY_00_PS 0x01 /* Power Status*/ -#define PHY_01_RHB 0x80 /* Root Hold-Off */ -#define PHY_01_IBR 0x80 /* Initiate Bus Reset */ -#define PHY_01_GAP_COUNT 0x3F -#define PHY_02_EXTENDED 0xE0 /* 0x7 for 1394a-compliant PHY */ -#define PHY_02_TOTAL_PORTS 0x1F -#define PHY_03_MAX_SPEED 0xE0 -#define PHY_03_DELAY 0x0F -#define PHY_04_LCTRL 0x80 /* Link Active Report Control */ -#define PHY_04_CONTENDER 0x40 -#define PHY_04_JITTER 0x38 -#define PHY_04_PWR_CLASS 0x07 /* Power Class */ -#define PHY_05_WATCHDOG 0x80 -#define PHY_05_ISBR 0x40 /* Initiate Short Bus Reset */ -#define PHY_05_LOOP 0x20 /* Loop Detect */ -#define PHY_05_PWR_FAIL 0x10 /* Cable Power Failure Detect */ -#define PHY_05_TIMEOUT 0x08 /* Arbitration State Machine Timeout */ -#define PHY_05_PORT_EVENT 0x04 /* Port Event Detect */ -#define PHY_05_ENAB_ACCEL 0x02 /* Enable Arbitration Acceleration */ -#define PHY_05_ENAB_MULTI 0x01 /* Ena. Multispeed Packet Concatenation */ +#define PHY_00_PHYSICAL_ID 0xFC +#define PHY_00_R 0x02 /* Root */ +#define PHY_00_PS 0x01 /* Power Status*/ +#define PHY_01_RHB 0x80 /* Root Hold-Off */ +#define PHY_01_IBR 0x80 /* Initiate Bus Reset */ +#define PHY_01_GAP_COUNT 0x3F +#define PHY_02_EXTENDED 0xE0 /* 0x7 for 1394a-compliant PHY */ +#define PHY_02_TOTAL_PORTS 0x1F +#define PHY_03_MAX_SPEED 0xE0 +#define PHY_03_DELAY 0x0F +#define PHY_04_LCTRL 0x80 /* Link Active Report Control */ +#define PHY_04_CONTENDER 0x40 +#define PHY_04_JITTER 0x38 +#define PHY_04_PWR_CLASS 0x07 /* Power Class */ +#define PHY_05_WATCHDOG 0x80 +#define PHY_05_ISBR 0x40 /* Initiate Short Bus Reset */ +#define PHY_05_LOOP 0x20 /* Loop Detect */ +#define PHY_05_PWR_FAIL 0x10 /* Cable Power Failure Detect */ +#define PHY_05_TIMEOUT 0x08 /* Arbitration State Machine Timeout */ +#define PHY_05_PORT_EVENT 0x04 /* Port Event Detect */ +#define PHY_05_ENAB_ACCEL 0x02 /* Enable Arbitration Acceleration */ +#define PHY_05_ENAB_MULTI 0x01 /* Ena. Multispeed Packet Concatenation */ #include #ifdef __BIG_ENDIAN_BITFIELD struct selfid { - u32 packet_identifier:2; /* always binary 10 */ - u32 phy_id:6; - /* byte */ - u32 extended:1; /* if true is struct ext_selfid */ - u32 link_active:1; - u32 gap_count:6; - /* byte */ - u32 speed:2; - u32 phy_delay:2; - u32 contender:1; - u32 power_class:3; - /* byte */ - u32 port0:2; - u32 port1:2; - u32 port2:2; - u32 initiated_reset:1; - u32 more_packets:1; + u32 packet_identifier:2; /* always binary 10 */ + u32 phy_id:6; + /* byte */ + u32 extended:1; /* if true is struct ext_selfid */ + u32 link_active:1; + u32 gap_count:6; + /* byte */ + u32 speed:2; + u32 phy_delay:2; + u32 contender:1; + u32 power_class:3; + /* byte */ + u32 port0:2; + u32 port1:2; + u32 port2:2; + u32 initiated_reset:1; + u32 more_packets:1; } __attribute__((packed)); struct ext_selfid { - u32 packet_identifier:2; /* always binary 10 */ - u32 phy_id:6; - /* byte */ - u32 extended:1; /* if false is struct selfid */ - u32 seq_nr:3; - u32 reserved:2; - u32 porta:2; - /* byte */ - u32 portb:2; - u32 portc:2; - u32 portd:2; - u32 porte:2; - /* byte */ - u32 portf:2; - u32 portg:2; - u32 porth:2; - u32 reserved2:1; - u32 more_packets:1; + u32 packet_identifier:2; /* always binary 10 */ + u32 phy_id:6; + /* byte */ + u32 extended:1; /* if false is struct selfid */ + u32 seq_nr:3; + u32 reserved:2; + u32 porta:2; + /* byte */ + u32 portb:2; + u32 portc:2; + u32 portd:2; + u32 porte:2; + /* byte */ + u32 portf:2; + u32 portg:2; + u32 porth:2; + u32 reserved2:1; + u32 more_packets:1; } __attribute__((packed)); #elif defined __LITTLE_ENDIAN_BITFIELD /* __BIG_ENDIAN_BITFIELD */ @@ -173,49 +172,48 @@ struct ext_selfid { */ struct selfid { - u32 phy_id:6; - u32 packet_identifier:2; /* always binary 10 */ - /* byte */ - u32 gap_count:6; - u32 link_active:1; - u32 extended:1; /* if true is struct ext_selfid */ - /* byte */ - u32 power_class:3; - u32 contender:1; - u32 phy_delay:2; - u32 speed:2; - /* byte */ - u32 more_packets:1; - u32 initiated_reset:1; - u32 port2:2; - u32 port1:2; - u32 port0:2; + u32 phy_id:6; + u32 packet_identifier:2; /* always binary 10 */ + /* byte */ + u32 gap_count:6; + u32 link_active:1; + u32 extended:1; /* if true is struct ext_selfid */ + /* byte */ + u32 power_class:3; + u32 contender:1; + u32 phy_delay:2; + u32 speed:2; + /* byte */ + u32 more_packets:1; + u32 initiated_reset:1; + u32 port2:2; + u32 port1:2; + u32 port0:2; } __attribute__((packed)); struct ext_selfid { - u32 phy_id:6; - u32 packet_identifier:2; /* always binary 10 */ - /* byte */ - u32 porta:2; - u32 reserved:2; - u32 seq_nr:3; - u32 extended:1; /* if false is struct selfid */ - /* byte */ - u32 porte:2; - u32 portd:2; - u32 portc:2; - u32 portb:2; - /* byte */ - u32 more_packets:1; - u32 reserved2:1; - u32 porth:2; - u32 portg:2; - u32 portf:2; + u32 phy_id:6; + u32 packet_identifier:2; /* always binary 10 */ + /* byte */ + u32 porta:2; + u32 reserved:2; + u32 seq_nr:3; + u32 extended:1; /* if false is struct selfid */ + /* byte */ + u32 porte:2; + u32 portd:2; + u32 portc:2; + u32 portb:2; + /* byte */ + u32 more_packets:1; + u32 reserved2:1; + u32 porth:2; + u32 portg:2; + u32 portf:2; } __attribute__((packed)); #else #error What? PDP endian? #endif /* __BIG_ENDIAN_BITFIELD */ - #endif /* _IEEE1394_IEEE1394_H */ diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h index 0ecbf335c64..31d9efccdc0 100644 --- a/drivers/ieee1394/ieee1394_core.h +++ b/drivers/ieee1394/ieee1394_core.h @@ -58,7 +58,6 @@ struct hpsb_packet { size_t header_size; size_t data_size; - struct hpsb_host *host; unsigned int generation; @@ -80,7 +79,7 @@ struct hpsb_packet { /* Set a task for when a packet completes */ void hpsb_set_packet_complete_task(struct hpsb_packet *packet, - void (*routine)(void *), void *data); + void (*routine)(void *), void *data); static inline struct hpsb_packet *driver_packet(struct list_head *l) { @@ -92,7 +91,6 @@ void abort_timedouts(unsigned long __opaque); struct hpsb_packet *hpsb_alloc_packet(size_t data_size); void hpsb_free_packet(struct hpsb_packet *packet); - /* * Generation counter for the complete 1394 subsystem. Generation gets * incremented on every change in the subsystem (e.g. bus reset). @@ -204,10 +202,14 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, #define IEEE1394_MINOR_BLOCK_EXPERIMENTAL 15 #define IEEE1394_CORE_DEV MKDEV(IEEE1394_MAJOR, 0) -#define IEEE1394_RAW1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16) -#define IEEE1394_VIDEO1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16) -#define IEEE1394_DV1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16) -#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16) +#define IEEE1394_RAW1394_DEV MKDEV(IEEE1394_MAJOR, \ + IEEE1394_MINOR_BLOCK_RAW1394 * 16) +#define IEEE1394_VIDEO1394_DEV MKDEV(IEEE1394_MAJOR, \ + IEEE1394_MINOR_BLOCK_VIDEO1394 * 16) +#define IEEE1394_DV1394_DEV MKDEV(IEEE1394_MAJOR, \ + IEEE1394_MINOR_BLOCK_DV1394 * 16) +#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, \ + IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16) /* return the index (within a minor number block) of a file */ static inline unsigned char ieee1394_file_to_instance(struct file *file) @@ -223,4 +225,3 @@ extern struct class hpsb_host_class; extern struct class *hpsb_protocol_class; #endif /* _IEEE1394_CORE_H */ - diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h index 45ba784fe6d..5f809f50845 100644 --- a/drivers/ieee1394/ieee1394_transactions.h +++ b/drivers/ieee1394/ieee1394_transactions.h @@ -3,30 +3,25 @@ #include "ieee1394_core.h" - -/* - * Get and free transaction labels. - */ int hpsb_get_tlabel(struct hpsb_packet *packet); void hpsb_free_tlabel(struct hpsb_packet *packet); - struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node, u64 addr, size_t length); struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node, - u64 addr, int extcode, quadlet_t *data, + u64 addr, int extcode, quadlet_t *data, quadlet_t arg); -struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node, - u64 addr, int extcode, octlet_t *data, - octlet_t arg); -struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, - quadlet_t data) ; -struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, - int length, int channel, - int tag, int sync); -struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node, - u64 addr, quadlet_t *buffer, size_t length); +struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, + nodeid_t node, u64 addr, int extcode, + octlet_t *data, octlet_t arg); +struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data); +struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, int length, + int channel, int tag, int sync); +struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host, + nodeid_t node, u64 addr, + quadlet_t *buffer, size_t length); struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, - int length, int channel, int tag, int sync); + int length, int channel, int tag, + int sync); /* * hpsb_packet_success - Make sense of the ack and reply codes and @@ -40,9 +35,8 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, */ int hpsb_packet_success(struct hpsb_packet *packet); - /* - * The generic read, write and lock functions. All recognize the local node ID + * The generic read and write functions. All recognize the local node ID * and act accordingly. Read and write automatically use quadlet commands if * length == 4 and and block commands otherwise (however, they do not yet * support lengths that are not a multiple of 4). You must explicitly specifiy diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h index 440d977031e..ed6fdd811a0 100644 --- a/drivers/ieee1394/ieee1394_types.h +++ b/drivers/ieee1394/ieee1394_types.h @@ -31,7 +31,6 @@ do { \ sema_init(&(_tp)->count, 63); \ } while (0) - typedef u32 quadlet_t; typedef u64 octlet_t; typedef u16 nodeid_t; @@ -54,16 +53,17 @@ typedef u16 arm_length_t; #define NODE_BUS_ARGS(__host, __nodeid) \ __host->id, NODEID_TO_NODE(__nodeid), NODEID_TO_BUS(__nodeid) -#define HPSB_PRINT(level, fmt, args...) printk(level "ieee1394: " fmt "\n" , ## args) +#define HPSB_PRINT(level, fmt, args...) \ + printk(level "ieee1394: " fmt "\n" , ## args) -#define HPSB_DEBUG(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args) -#define HPSB_INFO(fmt, args...) HPSB_PRINT(KERN_INFO, fmt , ## args) -#define HPSB_NOTICE(fmt, args...) HPSB_PRINT(KERN_NOTICE, fmt , ## args) -#define HPSB_WARN(fmt, args...) HPSB_PRINT(KERN_WARNING, fmt , ## args) -#define HPSB_ERR(fmt, args...) HPSB_PRINT(KERN_ERR, fmt , ## args) +#define HPSB_DEBUG(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args) +#define HPSB_INFO(fmt, args...) HPSB_PRINT(KERN_INFO, fmt , ## args) +#define HPSB_NOTICE(fmt, args...) HPSB_PRINT(KERN_NOTICE, fmt , ## args) +#define HPSB_WARN(fmt, args...) HPSB_PRINT(KERN_WARNING, fmt , ## args) +#define HPSB_ERR(fmt, args...) HPSB_PRINT(KERN_ERR, fmt , ## args) #ifdef CONFIG_IEEE1394_VERBOSEDEBUG -#define HPSB_VERBOSE(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args) +#define HPSB_VERBOSE(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args) #else #define HPSB_VERBOSE(fmt, args...) #endif @@ -77,23 +77,20 @@ typedef u16 arm_length_t; static inline void *memcpy_le32(u32 *dest, const u32 *__src, size_t count) { - void *tmp = dest; + void *tmp = dest; u32 *src = (u32 *)__src; - count /= 4; - - while (count--) { - *dest++ = swab32p(src++); - } - - return tmp; + count /= 4; + while (count--) + *dest++ = swab32p(src++); + return tmp; } #else static __inline__ void *memcpy_le32(u32 *dest, const u32 *src, size_t count) { - return memcpy(dest, src, count); + return memcpy(dest, src, count); } #endif /* __BIG_ENDIAN */ diff --git a/drivers/ieee1394/iso.h b/drivers/ieee1394/iso.h index 3efc60b33a8..ed639c4c510 100644 --- a/drivers/ieee1394/iso.h +++ b/drivers/ieee1394/iso.h @@ -17,28 +17,30 @@ /* high-level ISO interface */ -/* This API sends and receives isochronous packets on a large, - virtually-contiguous kernel memory buffer. The buffer may be mapped - into a user-space process for zero-copy transmission and reception. - - There are no explicit boundaries between packets in the buffer. A - packet may be transmitted or received at any location. However, - low-level drivers may impose certain restrictions on alignment or - size of packets. (e.g. in OHCI no packet may cross a page boundary, - and packets should be quadlet-aligned) -*/ +/* + * This API sends and receives isochronous packets on a large, + * virtually-contiguous kernel memory buffer. The buffer may be mapped + * into a user-space process for zero-copy transmission and reception. + * + * There are no explicit boundaries between packets in the buffer. A + * packet may be transmitted or received at any location. However, + * low-level drivers may impose certain restrictions on alignment or + * size of packets. (e.g. in OHCI no packet may cross a page boundary, + * and packets should be quadlet-aligned) + */ /* Packet descriptor - the API maintains a ring buffer of these packet - descriptors in kernel memory (hpsb_iso.infos[]). */ - + * descriptors in kernel memory (hpsb_iso.infos[]). */ struct hpsb_iso_packet_info { /* offset of data payload relative to the first byte of the buffer */ __u32 offset; - /* length of the data payload, in bytes (not including the isochronous header) */ + /* length of the data payload, in bytes (not including the isochronous + * header) */ __u16 len; - /* (recv only) the cycle number (mod 8000) on which the packet was received */ + /* (recv only) the cycle number (mod 8000) on which the packet was + * received */ __u16 cycle; /* (recv only) channel on which the packet was received */ @@ -48,12 +50,10 @@ struct hpsb_iso_packet_info { __u8 tag; __u8 sy; - /* - * length in bytes of the packet including header/trailer. - * MUST be at structure end, since the first part of this structure is also - * defined in raw1394.h (i.e. struct raw1394_iso_packet_info), is copied to - * userspace and is accessed there through libraw1394. - */ + /* length in bytes of the packet including header/trailer. + * MUST be at structure end, since the first part of this structure is + * also defined in raw1394.h (i.e. struct raw1394_iso_packet_info), is + * copied to userspace and is accessed there through libraw1394. */ __u16 total_len; }; @@ -75,8 +75,8 @@ struct hpsb_iso { void *hostdata; /* a function to be called (from interrupt context) after - outgoing packets have been sent, or incoming packets have - arrived */ + * outgoing packets have been sent, or incoming packets have + * arrived */ void (*callback)(struct hpsb_iso*); /* wait for buffer space */ @@ -88,7 +88,7 @@ struct hpsb_iso { /* greatest # of packets between interrupts - controls - the maximum latency of the buffer */ + * the maximum latency of the buffer */ int irq_interval; /* the buffer for packet data payloads */ @@ -112,8 +112,8 @@ struct hpsb_iso { int pkt_dma; /* how many packets, starting at first_packet: - (transmit) are ready to be filled with data - (receive) contain received data */ + * (transmit) are ready to be filled with data + * (receive) contain received data */ int n_ready_packets; /* how many times the buffer has overflowed or underflowed */ @@ -134,7 +134,7 @@ struct hpsb_iso { int start_cycle; /* cycle at which next packet will be transmitted, - -1 if not known */ + * -1 if not known */ int xmit_cycle; /* ringbuffer of packet descriptors in regular kernel memory @@ -170,25 +170,30 @@ int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel); int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask); /* start/stop DMA */ -int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle, int prebuffer); -int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle, int tag_mask, int sync); +int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle, + int prebuffer); +int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle, + int tag_mask, int sync); void hpsb_iso_stop(struct hpsb_iso *iso); /* deallocate buffer and DMA context */ void hpsb_iso_shutdown(struct hpsb_iso *iso); -/* queue a packet for transmission. 'offset' is relative to the beginning of the - DMA buffer, where the packet's data payload should already have been placed */ -int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy); +/* queue a packet for transmission. + * 'offset' is relative to the beginning of the DMA buffer, where the packet's + * data payload should already have been placed. */ +int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, + u8 tag, u8 sy); /* wait until all queued packets have been transmitted to the bus */ int hpsb_iso_xmit_sync(struct hpsb_iso *iso); /* N packets have been read out of the buffer, re-use the buffer space */ -int hpsb_iso_recv_release_packets(struct hpsb_iso *recv, unsigned int n_packets); +int hpsb_iso_recv_release_packets(struct hpsb_iso *recv, + unsigned int n_packets); /* check for arrival of new packets immediately (even if irq_interval - has not yet been reached) */ + * has not yet been reached) */ int hpsb_iso_recv_flush(struct hpsb_iso *iso); /* returns # of packets ready to send or receive */ @@ -197,14 +202,15 @@ int hpsb_iso_n_ready(struct hpsb_iso *iso); /* the following are callbacks available to low-level drivers */ /* call after a packet has been transmitted to the bus (interrupt context is OK) - 'cycle' is the _exact_ cycle the packet was sent on - 'error' should be non-zero if some sort of error occurred when sending the packet -*/ + * 'cycle' is the _exact_ cycle the packet was sent on + * 'error' should be non-zero if some sort of error occurred when sending the + * packet */ void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error); /* call after a packet has been received (interrupt context OK) */ void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, - u16 total_len, u16 cycle, u8 channel, u8 tag, u8 sy); + u16 total_len, u16 cycle, u8 channel, u8 tag, + u8 sy); /* call to wake waiting processes after buffer space has opened up. */ void hpsb_iso_wake(struct hpsb_iso *iso); diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h index 0b26616e16c..b35c1b5c8d8 100644 --- a/drivers/ieee1394/nodemgr.h +++ b/drivers/ieee1394/nodemgr.h @@ -44,7 +44,6 @@ struct bus_options { u16 max_rec; /* Maximum packet size node can receive */ }; - #define UNIT_DIRECTORY_VENDOR_ID 0x01 #define UNIT_DIRECTORY_MODEL_ID 0x02 #define UNIT_DIRECTORY_SPECIFIER_ID 0x04 @@ -59,8 +58,8 @@ struct bus_options { * unit directory for each of these protocols. */ struct unit_directory { - struct node_entry *ne; /* The node which this directory belongs to */ - octlet_t address; /* Address of the unit directory on the node */ + struct node_entry *ne; /* The node which this directory belongs to */ + octlet_t address; /* Address of the unit directory on the node */ u8 flags; /* Indicates which entries were read */ quadlet_t vendor_id; @@ -79,11 +78,10 @@ struct unit_directory { int length; /* Number of quadlets */ struct device device; - struct class_device class_dev; struct csr1212_keyval *ud_kv; - u32 lun; /* logical unit number immediate value */ + u32 lun; /* logical unit number immediate value */ }; struct node_entry { @@ -106,7 +104,6 @@ struct node_entry { struct hpsb_tlabel_pool *tpool; struct device device; - struct class_device class_dev; /* Means this node is not attached anymore */ @@ -153,8 +150,8 @@ static inline int hpsb_node_entry_valid(struct node_entry *ne) /* * This will fill in the given, pre-initialised hpsb_packet with the current * information from the node entry (host, node ID, generation number). It will - * return false if the node owning the GUID is not accessible (and not modify the - * hpsb_packet) and return true otherwise. + * return false if the node owning the GUID is not accessible (and not modify + * the hpsb_packet) and return true otherwise. * * Note that packet sending may still fail in hpsb_send_packet if a bus reset * happens while you are trying to set up the packet (due to obsolete generation @@ -170,16 +167,13 @@ int hpsb_node_write(struct node_entry *ne, u64 addr, int hpsb_node_lock(struct node_entry *ne, u64 addr, int extcode, quadlet_t *data, quadlet_t arg); - /* Iterate the hosts, calling a given function with supplied data for each * host. */ int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *)); - int init_ieee1394_nodemgr(void); void cleanup_ieee1394_nodemgr(void); - /* The template for a host device */ extern struct device nodemgr_dev_template_host; -- cgit v1.2.3 From de4394f13cc843fae2a3ba2df752ee20e6e779a8 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:29 -0400 Subject: [PATCH] ieee1394: update #include directives in midlayer header files Remove unnecessary includes, add missing includes. Use forward type declarations for some structs. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/csr.h | 6 ++---- drivers/ieee1394/dma.c | 7 +++++-- drivers/ieee1394/dma.h | 7 +++++-- drivers/ieee1394/dv1394.c | 12 ++++++------ drivers/ieee1394/eth1394.c | 11 ++++++----- drivers/ieee1394/highlevel.h | 10 ++++++++++ drivers/ieee1394/hosts.h | 10 ++++++---- drivers/ieee1394/ieee1394_core.h | 10 +++++++--- drivers/ieee1394/ieee1394_hotplug.h | 3 +-- drivers/ieee1394/ieee1394_transactions.h | 7 ++++++- drivers/ieee1394/ieee1394_types.h | 7 ++----- drivers/ieee1394/iso.c | 5 ++++- drivers/ieee1394/iso.h | 7 ++++++- drivers/ieee1394/nodemgr.c | 9 +++++---- drivers/ieee1394/nodemgr.h | 10 ++++++++-- drivers/ieee1394/raw1394.c | 11 ++++++----- drivers/ieee1394/video1394.c | 12 ++++++------ 17 files changed, 91 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/csr.h b/drivers/ieee1394/csr.h index 0655596f25d..2bc080f7651 100644 --- a/drivers/ieee1394/csr.h +++ b/drivers/ieee1394/csr.h @@ -1,12 +1,10 @@ - #ifndef _IEEE1394_CSR_H #define _IEEE1394_CSR_H -#ifdef CONFIG_PREEMPT -#include -#endif +#include #include "csr1212.h" +#include "ieee1394_types.h" #define CSR_REGISTER_BASE 0xfffff0000000ULL diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c index ca5167de707..c68f328e1a2 100644 --- a/drivers/ieee1394/dma.c +++ b/drivers/ieee1394/dma.c @@ -7,10 +7,13 @@ * directory of the kernel sources for details. */ +#include #include -#include +#include #include -#include +#include +#include + #include "dma.h" /* dma_prog_region */ diff --git a/drivers/ieee1394/dma.h b/drivers/ieee1394/dma.h index b0f0885c455..a1682aba71c 100644 --- a/drivers/ieee1394/dma.h +++ b/drivers/ieee1394/dma.h @@ -10,8 +10,11 @@ #ifndef IEEE1394_DMA_H #define IEEE1394_DMA_H -#include -#include +#include + +struct pci_dev; +struct scatterlist; +struct vm_area_struct; /** * struct dma_prog_region - small contiguous DMA buffer diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 87532dd4337..bdc50f25fb4 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -110,15 +110,15 @@ #include #include +#include "dv1394.h" +#include "dv1394-private.h" +#include "highlevel.h" +#include "hosts.h" #include "ieee1394.h" +#include "ieee1394_core.h" +#include "ieee1394_hotplug.h" #include "ieee1394_types.h" #include "nodemgr.h" -#include "hosts.h" -#include "ieee1394_core.h" -#include "highlevel.h" -#include "dv1394.h" -#include "dv1394-private.h" - #include "ohci1394.h" /* DEBUG LEVELS: diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 2d5b57be98c..09826be86aa 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -67,16 +67,17 @@ #include #include +#include "config_roms.h" #include "csr1212.h" -#include "ieee1394_types.h" +#include "eth1394.h" +#include "highlevel.h" +#include "ieee1394.h" #include "ieee1394_core.h" +#include "ieee1394_hotplug.h" #include "ieee1394_transactions.h" -#include "ieee1394.h" -#include "highlevel.h" +#include "ieee1394_types.h" #include "iso.h" #include "nodemgr.h" -#include "eth1394.h" -#include "config_roms.h" #define ETH1394_PRINT_G(level, fmt, args...) \ printk(level "%s: " fmt, driver_name, ## args) diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h index 134bb6c3ead..50f2dd2c7e2 100644 --- a/drivers/ieee1394/highlevel.h +++ b/drivers/ieee1394/highlevel.h @@ -1,6 +1,16 @@ #ifndef IEEE1394_HIGHLEVEL_H #define IEEE1394_HIGHLEVEL_H +#include +#include +#include + +struct module; + +#include "ieee1394_types.h" + +struct hpsb_host; + /* internal to ieee1394 core */ struct hpsb_address_serve { struct list_head host_list; /* per host list */ diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index 857d7d80bc8..b911e2af99a 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h @@ -2,17 +2,19 @@ #define _IEEE1394_HOSTS_H #include -#include #include -#include #include +#include +#include +#include +#include -#include +struct pci_dev; +struct module; #include "ieee1394_types.h" #include "csr.h" - struct hpsb_packet; struct hpsb_iso; diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h index 31d9efccdc0..1ce172b2856 100644 --- a/drivers/ieee1394/ieee1394_core.h +++ b/drivers/ieee1394/ieee1394_core.h @@ -1,12 +1,16 @@ - #ifndef _IEEE1394_CORE_H #define _IEEE1394_CORE_H -#include +#include +#include +#include +#include +#include #include #include -#include "hosts.h" +#include "hosts.h" +#include "ieee1394_types.h" struct hpsb_packet { /* This struct is basically read-only for hosts with the exception of diff --git a/drivers/ieee1394/ieee1394_hotplug.h b/drivers/ieee1394/ieee1394_hotplug.h index 5be70d31b00..183d93188d4 100644 --- a/drivers/ieee1394/ieee1394_hotplug.h +++ b/drivers/ieee1394/ieee1394_hotplug.h @@ -1,9 +1,8 @@ #ifndef _IEEE1394_HOTPLUG_H #define _IEEE1394_HOTPLUG_H -#include -#include #include +#include /* Unit spec id and sw version entry for some protocols */ #define AVC_UNIT_SPEC_ID_ENTRY 0x0000A02D diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h index 5f809f50845..290d37060b0 100644 --- a/drivers/ieee1394/ieee1394_transactions.h +++ b/drivers/ieee1394/ieee1394_transactions.h @@ -1,7 +1,12 @@ #ifndef _IEEE1394_TRANSACTIONS_H #define _IEEE1394_TRANSACTIONS_H -#include "ieee1394_core.h" +#include + +#include "ieee1394_types.h" + +struct hpsb_packet; +struct hpsb_host; int hpsb_get_tlabel(struct hpsb_packet *packet); void hpsb_free_tlabel(struct hpsb_packet *packet); diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h index ed6fdd811a0..6c246913b16 100644 --- a/drivers/ieee1394/ieee1394_types.h +++ b/drivers/ieee1394/ieee1394_types.h @@ -1,17 +1,14 @@ - #ifndef _IEEE1394_TYPES_H #define _IEEE1394_TYPES_H #include -#include #include -#include #include #include +#include -#include #include - +#include /* Transaction Label handling */ struct hpsb_tlabel_pool { diff --git a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c index f26680ebef7..08bd15d2a7b 100644 --- a/drivers/ieee1394/iso.c +++ b/drivers/ieee1394/iso.c @@ -9,8 +9,11 @@ * directory of the kernel sources for details. */ -#include +#include #include +#include + +#include "hosts.h" #include "iso.h" void hpsb_iso_stop(struct hpsb_iso *iso) diff --git a/drivers/ieee1394/iso.h b/drivers/ieee1394/iso.h index ed639c4c510..1210a97e868 100644 --- a/drivers/ieee1394/iso.h +++ b/drivers/ieee1394/iso.h @@ -12,9 +12,14 @@ #ifndef IEEE1394_ISO_H #define IEEE1394_ISO_H -#include "hosts.h" +#include +#include +#include + #include "dma.h" +struct hpsb_host; + /* high-level ISO interface */ /* diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index dfed2ed2ed9..b873e5d5795 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -21,13 +21,14 @@ #include #include -#include "ieee1394_types.h" +#include "csr.h" +#include "highlevel.h" +#include "hosts.h" #include "ieee1394.h" #include "ieee1394_core.h" -#include "hosts.h" +#include "ieee1394_hotplug.h" +#include "ieee1394_types.h" #include "ieee1394_transactions.h" -#include "highlevel.h" -#include "csr.h" #include "nodemgr.h" static int ignore_drivers; diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h index b35c1b5c8d8..f649c9d321b 100644 --- a/drivers/ieee1394/nodemgr.h +++ b/drivers/ieee1394/nodemgr.h @@ -21,9 +21,15 @@ #define _IEEE1394_NODEMGR_H #include -#include "csr1212.h" +#include + #include "ieee1394_core.h" -#include "ieee1394_hotplug.h" +#include "ieee1394_types.h" + +struct csr1212_csr; +struct csr1212_keyval; +struct hpsb_host; +struct ieee1394_device_id; /* '1' '3' '9' '4' in ASCII */ #define IEEE1394_BUSID_MAGIC __constant_cpu_to_be32(0x31333934) diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 571ea68c0cf..46c88e8a24f 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -44,14 +44,15 @@ #include #include "csr1212.h" +#include "highlevel.h" +#include "hosts.h" #include "ieee1394.h" -#include "ieee1394_types.h" #include "ieee1394_core.h" -#include "nodemgr.h" -#include "hosts.h" -#include "highlevel.h" -#include "iso.h" +#include "ieee1394_hotplug.h" #include "ieee1394_transactions.h" +#include "ieee1394_types.h" +#include "iso.h" +#include "nodemgr.h" #include "raw1394.h" #include "raw1394-private.h" diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index c6e3f02bc6d..6b5353d81ae 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -49,16 +49,16 @@ #include #include -#include "ieee1394.h" -#include "ieee1394_types.h" +#include "dma.h" +#include "highlevel.h" #include "hosts.h" +#include "ieee1394.h" #include "ieee1394_core.h" -#include "highlevel.h" -#include "video1394.h" +#include "ieee1394_hotplug.h" +#include "ieee1394_types.h" #include "nodemgr.h" -#include "dma.h" - #include "ohci1394.h" +#include "video1394.h" #define ISO_CHANNELS 64 -- cgit v1.2.3 From 66faadfac3b8488d27374acaa407e3bd7380131a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:30 -0400 Subject: [PATCH] ieee1394: remove redundant code from ieee1394_hotplug.h Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/ieee1394_hotplug.h | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ieee1394_hotplug.h b/drivers/ieee1394/ieee1394_hotplug.h index 183d93188d4..dd5500ed832 100644 --- a/drivers/ieee1394/ieee1394_hotplug.h +++ b/drivers/ieee1394/ieee1394_hotplug.h @@ -1,32 +1,19 @@ #ifndef _IEEE1394_HOTPLUG_H #define _IEEE1394_HOTPLUG_H -#include -#include - /* Unit spec id and sw version entry for some protocols */ #define AVC_UNIT_SPEC_ID_ENTRY 0x0000A02D #define AVC_SW_VERSION_ENTRY 0x00010001 #define CAMERA_UNIT_SPEC_ID_ENTRY 0x0000A02D #define CAMERA_SW_VERSION_ENTRY 0x00000100 -/* Check to make sure this all isn't already defined */ -#ifndef IEEE1394_MATCH_VENDOR_ID - -#define IEEE1394_MATCH_VENDOR_ID 0x0001 -#define IEEE1394_MATCH_MODEL_ID 0x0002 -#define IEEE1394_MATCH_SPECIFIER_ID 0x0004 -#define IEEE1394_MATCH_VERSION 0x0008 - -struct ieee1394_device_id { - u32 match_flags; - u32 vendor_id; - u32 model_id; - u32 specifier_id; - u32 version; - void *driver_data; -}; - -#endif +/* /include/linux/mod_devicetable.h defines: + * IEEE1394_MATCH_VENDOR_ID + * IEEE1394_MATCH_MODEL_ID + * IEEE1394_MATCH_SPECIFIER_ID + * IEEE1394_MATCH_VERSION + * struct ieee1394_device_id + */ +#include #endif /* _IEEE1394_HOTPLUG_H */ -- cgit v1.2.3 From d83e7d8e7e9f41a9d0e68aaf24ec4e785dd071bb Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:31 -0400 Subject: [PATCH] ieee1394: remove unused macros HPSB_PANIC and HPSB_TRACE Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/ieee1394_transactions.c | 6 +++--- drivers/ieee1394/ieee1394_types.h | 5 ----- 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c index a114b91d606..751960037e2 100644 --- a/drivers/ieee1394/ieee1394_transactions.c +++ b/drivers/ieee1394/ieee1394_transactions.c @@ -14,6 +14,7 @@ #include #include +#include #include #include "ieee1394.h" @@ -214,7 +215,7 @@ int hpsb_packet_success(struct hpsb_packet *packet) packet->node_id); return -EAGAIN; } - HPSB_PANIC("reached unreachable code 1 in %s", __FUNCTION__); + BUG(); case ACK_BUSY_X: case ACK_BUSY_A: @@ -261,8 +262,7 @@ int hpsb_packet_success(struct hpsb_packet *packet) packet->ack_code, packet->node_id, packet->tcode); return -EAGAIN; } - - HPSB_PANIC("reached unreachable code 2 in %s", __FUNCTION__); + BUG(); } struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node, diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h index 6c246913b16..16fd2d0b5ed 100644 --- a/drivers/ieee1394/ieee1394_types.h +++ b/drivers/ieee1394/ieee1394_types.h @@ -65,11 +65,6 @@ typedef u16 arm_length_t; #define HPSB_VERBOSE(fmt, args...) #endif -#define HPSB_PANIC(fmt, args...) panic("ieee1394: " fmt "\n" , ## args) - -#define HPSB_TRACE() HPSB_PRINT(KERN_INFO, "TRACE - %s, %s(), line %d", __FILE__, __FUNCTION__, __LINE__) - - #ifdef __BIG_ENDIAN static inline void *memcpy_le32(u32 *dest, const u32 *__src, size_t count) -- cgit v1.2.3 From d8831d5554c2f295a6746e9d3b4cbd8bb13a540f Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:31 -0400 Subject: [PATCH] ieee1394: clean up declarations of hpsb_*_config_rom hpsb_update_config_rom() is defined in csr.c, not hosts.c. hpsb_get_config_rom() does not exist. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/csr.h | 5 +++++ drivers/ieee1394/hosts.h | 7 ------- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/csr.h b/drivers/ieee1394/csr.h index 2bc080f7651..f11546550d8 100644 --- a/drivers/ieee1394/csr.h +++ b/drivers/ieee1394/csr.h @@ -91,4 +91,9 @@ extern struct csr1212_bus_ops csr_bus_ops; int init_csr(void); void cleanup_csr(void); +/* hpsb_update_config_rom() is deprecated */ +struct hpsb_host; +int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, + size_t size, unsigned char rom_version); + #endif /* _IEEE1394_CSR_H */ diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index b911e2af99a..69a7c9ff5ed 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h @@ -205,13 +205,6 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, int hpsb_add_host(struct hpsb_host *host); void hpsb_remove_host(struct hpsb_host *h); -/* The following 2 functions are deprecated and will be removed when the - * raw1394/libraw1394 update is complete. */ -int hpsb_update_config_rom(struct hpsb_host *host, - const quadlet_t *new_rom, size_t size, unsigned char rom_version); -int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer, - size_t buffersize, size_t *rom_size, unsigned char *rom_version); - /* Updates the configuration rom image of a host. rom_version must be the * current version, otherwise it will fail with return value -1. If this * host does not support config-rom-update, it will return -EINVAL. -- cgit v1.2.3 From 438bd525e5240a48233cd3290f7fe66ff0167e20 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:32 -0400 Subject: [PATCH] ieee1394: dv1394: sem2mutex conversion Signed-off-by: Stefan Richter (not runtime-tested) Signed-off-by: Ben Collins --- drivers/ieee1394/dv1394-private.h | 6 +++--- drivers/ieee1394/dv1394.c | 31 ++++++++++++++++--------------- 2 files changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/dv1394-private.h b/drivers/ieee1394/dv1394-private.h index 80b5ac7fe38..7d1d2845b42 100644 --- a/drivers/ieee1394/dv1394-private.h +++ b/drivers/ieee1394/dv1394-private.h @@ -460,7 +460,7 @@ struct video_card { int dma_running; /* - 3) the sleeping semaphore 'sem' - this is used from process context only, + 3) the sleeping mutex 'mtx' - this is used from process context only, to serialize various operations on the video_card. Even though only one open() is allowed, we still need to prevent multiple threads of execution from entering calls like read, write, ioctl, etc. @@ -468,9 +468,9 @@ struct video_card { I honestly can't think of a good reason to use dv1394 from several threads at once, but we need to serialize anyway to prevent oopses =). - NOTE: if you need both spinlock and sem, take sem first to avoid deadlock! + NOTE: if you need both spinlock and mtx, take mtx first to avoid deadlock! */ - struct semaphore sem; + struct mutex mtx; /* people waiting for buffer space, please form a line here... */ wait_queue_head_t waitq; diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index bdc50f25fb4..6e71d68b109 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -95,6 +95,7 @@ #include #include #include +#include #include #include #include @@ -247,7 +248,7 @@ static void frame_delete(struct frame *f) Frame_prepare() must be called OUTSIDE the video->spinlock. However, frame_prepare() must still be serialized, so - it should be called WITH the video->sem taken. + it should be called WITH the video->mtx taken. */ static void frame_prepare(struct video_card *video, unsigned int this_frame) @@ -1271,7 +1272,7 @@ static int dv1394_mmap(struct file *file, struct vm_area_struct *vma) int retval = -EINVAL; /* serialize mmap */ - down(&video->sem); + mutex_lock(&video->mtx); if ( ! video_card_initialized(video) ) { retval = do_dv1394_init_default(video); @@ -1281,7 +1282,7 @@ static int dv1394_mmap(struct file *file, struct vm_area_struct *vma) retval = dma_region_mmap(&video->dv_buf, file, vma); out: - up(&video->sem); + mutex_unlock(&video->mtx); return retval; } @@ -1337,17 +1338,17 @@ static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t /* serialize this to prevent multi-threaded mayhem */ if (file->f_flags & O_NONBLOCK) { - if (down_trylock(&video->sem)) + if (!mutex_trylock(&video->mtx)) return -EAGAIN; } else { - if (down_interruptible(&video->sem)) + if (mutex_lock_interruptible(&video->mtx)) return -ERESTARTSYS; } if ( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); if (ret) { - up(&video->sem); + mutex_unlock(&video->mtx); return ret; } } @@ -1418,7 +1419,7 @@ static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t remove_wait_queue(&video->waitq, &wait); set_current_state(TASK_RUNNING); - up(&video->sem); + mutex_unlock(&video->mtx); return ret; } @@ -1434,17 +1435,17 @@ static ssize_t dv1394_read(struct file *file, char __user *buffer, size_t count /* serialize this to prevent multi-threaded mayhem */ if (file->f_flags & O_NONBLOCK) { - if (down_trylock(&video->sem)) + if (!mutex_trylock(&video->mtx)) return -EAGAIN; } else { - if (down_interruptible(&video->sem)) + if (mutex_lock_interruptible(&video->mtx)) return -ERESTARTSYS; } if ( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); if (ret) { - up(&video->sem); + mutex_unlock(&video->mtx); return ret; } video->continuity_counter = -1; @@ -1526,7 +1527,7 @@ static ssize_t dv1394_read(struct file *file, char __user *buffer, size_t count remove_wait_queue(&video->waitq, &wait); set_current_state(TASK_RUNNING); - up(&video->sem); + mutex_unlock(&video->mtx); return ret; } @@ -1547,12 +1548,12 @@ static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg) /* serialize this to prevent multi-threaded mayhem */ if (file->f_flags & O_NONBLOCK) { - if (down_trylock(&video->sem)) { + if (!mutex_trylock(&video->mtx)) { unlock_kernel(); return -EAGAIN; } } else { - if (down_interruptible(&video->sem)) { + if (mutex_lock_interruptible(&video->mtx)) { unlock_kernel(); return -ERESTARTSYS; } @@ -1778,7 +1779,7 @@ static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } out: - up(&video->sem); + mutex_unlock(&video->mtx); unlock_kernel(); return ret; } @@ -2253,7 +2254,7 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes clear_bit(0, &video->open); spin_lock_init(&video->spinlock); video->dma_running = 0; - init_MUTEX(&video->sem); + mutex_init(&video->mtx); init_waitqueue_head(&video->waitq); video->fasync = NULL; -- cgit v1.2.3 From 45289bf6ac70b106f5000d10b040e4485dd3e9d5 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:33 -0400 Subject: [PATCH] ieee1394: raw1394: remove redundant counting semaphore An already existing wait queue replaces raw1394's complete_sem which was maintained in parallel to the wait queue. The role of the semaphore's counter is taken over by a direct check of what was really counted: The presence of items in the list of completed requests. Notes: - raw1394_release() sleeps uninterruptibly until all requests were completed. This is the same behaviour as before the patch. - The macros wait_event and wait_event_interruptible are called with a condition argument which has a side effect, i.e. manipulation of the requests list. This side effect happens only if the condition is true. The patch relies on the fact that wait_event[_interruptible] does not evaluate the condition again after it became true. - The diffstat looks unfavorable with respect to added lines of code. However 19 of them are comments, and some are due to separation of existing code blocks into two small helper functions. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/raw1394-private.h | 3 +- drivers/ieee1394/raw1394.c | 91 ++++++++++++++++++++++++-------------- 2 files changed, 58 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h index c93587be9ca..c7731d1bcd8 100644 --- a/drivers/ieee1394/raw1394-private.h +++ b/drivers/ieee1394/raw1394-private.h @@ -29,9 +29,8 @@ struct file_info { struct list_head req_pending; struct list_head req_complete; - struct semaphore complete_sem; spinlock_t reqlists_lock; - wait_queue_head_t poll_wait_complete; + wait_queue_head_t wait_complete; struct list_head addr_list; diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 46c88e8a24f..840b705fd5d 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -133,10 +133,9 @@ static void free_pending_request(struct pending_request *req) static void __queue_complete_req(struct pending_request *req) { struct file_info *fi = req->file_info; - list_move_tail(&req->list, &fi->req_complete); - up(&fi->complete_sem); - wake_up_interruptible(&fi->poll_wait_complete); + list_move_tail(&req->list, &fi->req_complete); + wake_up(&fi->wait_complete); } static void queue_complete_req(struct pending_request *req) @@ -464,13 +463,36 @@ raw1394_compat_read(const char __user *buf, struct raw1394_request *r) #endif +/* get next completed request (caller must hold fi->reqlists_lock) */ +static inline struct pending_request *__next_complete_req(struct file_info *fi) +{ + struct list_head *lh; + struct pending_request *req = NULL; + + if (!list_empty(&fi->req_complete)) { + lh = fi->req_complete.next; + list_del(lh); + req = list_entry(lh, struct pending_request, list); + } + return req; +} + +/* atomically get next completed request */ +static struct pending_request *next_complete_req(struct file_info *fi) +{ + unsigned long flags; + struct pending_request *req; + + spin_lock_irqsave(&fi->reqlists_lock, flags); + req = __next_complete_req(fi); + spin_unlock_irqrestore(&fi->reqlists_lock, flags); + return req; +} static ssize_t raw1394_read(struct file *file, char __user * buffer, size_t count, loff_t * offset_is_ignored) { - unsigned long flags; struct file_info *fi = (struct file_info *)file->private_data; - struct list_head *lh; struct pending_request *req; ssize_t ret; @@ -488,22 +510,21 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer, } if (file->f_flags & O_NONBLOCK) { - if (down_trylock(&fi->complete_sem)) { + if (!(req = next_complete_req(fi))) return -EAGAIN; - } } else { - if (down_interruptible(&fi->complete_sem)) { + /* + * NB: We call the macro wait_event_interruptible() with a + * condition argument with side effect. This is only possible + * because the side effect does not occur until the condition + * became true, and wait_event_interruptible() won't evaluate + * the condition again after that. + */ + if (wait_event_interruptible(fi->wait_complete, + (req = next_complete_req(fi)))) return -ERESTARTSYS; - } } - spin_lock_irqsave(&fi->reqlists_lock, flags); - lh = fi->req_complete.next; - list_del(lh); - spin_unlock_irqrestore(&fi->reqlists_lock, flags); - - req = list_entry(lh, struct pending_request, list); - if (req->req.length) { if (copy_to_user(int2ptr(req->req.recvb), req->data, req->req.length)) { @@ -2745,7 +2766,7 @@ static unsigned int raw1394_poll(struct file *file, poll_table * pt) unsigned int mask = POLLOUT | POLLWRNORM; unsigned long flags; - poll_wait(file, &fi->poll_wait_complete, pt); + poll_wait(file, &fi->wait_complete, pt); spin_lock_irqsave(&fi->reqlists_lock, flags); if (!list_empty(&fi->req_complete)) { @@ -2770,9 +2791,8 @@ static int raw1394_open(struct inode *inode, struct file *file) fi->state = opened; INIT_LIST_HEAD(&fi->req_pending); INIT_LIST_HEAD(&fi->req_complete); - sema_init(&fi->complete_sem, 0); spin_lock_init(&fi->reqlists_lock); - init_waitqueue_head(&fi->poll_wait_complete); + init_waitqueue_head(&fi->wait_complete); INIT_LIST_HEAD(&fi->addr_list); file->private_data = fi; @@ -2785,7 +2805,7 @@ static int raw1394_release(struct inode *inode, struct file *file) struct file_info *fi = file->private_data; struct list_head *lh; struct pending_request *req; - int done = 0, i, fail = 0; + int i, fail; int retval = 0; struct list_head *entry; struct arm_addr *addr = NULL; @@ -2865,25 +2885,28 @@ static int raw1394_release(struct inode *inode, struct file *file) "error(s) occurred \n"); } - while (!done) { + for (;;) { + /* This locked section guarantees that neither + * complete nor pending requests exist once i!=0 */ spin_lock_irqsave(&fi->reqlists_lock, flags); - - while (!list_empty(&fi->req_complete)) { - lh = fi->req_complete.next; - list_del(lh); - - req = list_entry(lh, struct pending_request, list); - + while ((req = __next_complete_req(fi))) free_pending_request(req); - } - - if (list_empty(&fi->req_pending)) - done = 1; + i = list_empty(&fi->req_pending); spin_unlock_irqrestore(&fi->reqlists_lock, flags); - if (!done) - down_interruptible(&fi->complete_sem); + if (i) + break; + /* + * Sleep until more requests can be freed. + * + * NB: We call the macro wait_event() with a condition argument + * with side effect. This is only possible because the side + * effect does not occur until the condition became true, and + * wait_event() won't evaluate the condition again after that. + */ + wait_event(fi->wait_complete, (req = next_complete_req(fi))); + free_pending_request(req); } /* Remove any sub-trees left by user space programs */ -- cgit v1.2.3 From 1ee0dc51fb68d2d25888250c554492c4926c5ec1 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:33 -0400 Subject: [PATCH] ieee1394: nodemgr: remove unnecessary includes Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/nodemgr.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index b873e5d5795..bfab7933d68 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -12,12 +12,8 @@ #include #include #include -#include -#include -#include #include #include -#include #include #include -- cgit v1.2.3 From 40fd89cc54a8a67c81b5aa40b22c4f40b39e47b9 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:34 -0400 Subject: [PATCH] ieee1394: nodemgr: do not spawn kernel_thread for sysfs rescan nodemgr.c::fw_set_rescan() is used to re-run the driver core over nodemgr's representation of unit directories in order to initiate protocol driver probes. It is initiated via write access to one of nodemgr's sysfs attributes. The purpose is to attach drivers to units after switching a unit's ignore_driver attribute from 1 to 0. It is not really necessary to fork a kernel_thread for this job. The call to kernel_thread() can be eliminated to avoid the deprecated API and to simplify the code a bit. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/nodemgr.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index bfab7933d68..1ce3d8a14ae 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -405,26 +405,11 @@ static ssize_t fw_get_destroy_node(struct bus_type *bus, char *buf) } static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node); -static int nodemgr_rescan_bus_thread(void *__unused) -{ - /* No userlevel access needed */ - daemonize("kfwrescan"); - - bus_rescan_devices(&ieee1394_bus_type); - - return 0; -} static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf, size_t count) { - int state = simple_strtoul(buf, NULL, 10); - - /* Don't wait for this, or care about errors. Root could do - * something stupid and spawn this a lot of times, but that's - * root's fault. */ - if (state == 1) - kernel_thread(nodemgr_rescan_bus_thread, NULL, CLONE_KERNEL); - + if (simple_strtoul(buf, NULL, 10) == 1) + bus_rescan_devices(&ieee1394_bus_type); return count; } static ssize_t fw_get_rescan(struct bus_type *bus, char *buf) -- cgit v1.2.3 From 3a632fe2321f6440ea8184b99549c74b912f5cef Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:35 -0400 Subject: [PATCH] ieee1394: nodemgr: make module parameter ignore_drivers writable Nodemgr's ignore_drivers variable is exposed as a module load parameter (therefore also as a sysfs attribute below /sys/module) and additionally as an attribute below /sys/bus/ieee1394. Since the latter is writable, make the former writable too. Note, the bus's attribute ignore_drivers is only relevant to newly added units, not to present or suspended or resuming units. Those have their own attribute ignore_driver. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/nodemgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 1ce3d8a14ae..04b62eca647 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -28,7 +28,7 @@ #include "nodemgr.h" static int ignore_drivers; -module_param(ignore_drivers, int, 0444); +module_param(ignore_drivers, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ignore_drivers, "Disable automatic probing for drivers."); struct nodemgr_csr_info { -- cgit v1.2.3 From d2f119fe319528da8c76a1107459d6f478cbf28c Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:35 -0400 Subject: [PATCH] ieee1394: nodemgr: switch to kthread api, replace reset semaphore Convert nodemgr's host thread from kernel_thread to kthread and its sleep/restart mechanism from a counting semaphore to a schedule()/ wake_up_process() scheme. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/nodemgr.c | 120 ++++++++++++++++----------------------------- 1 file changed, 41 insertions(+), 79 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 04b62eca647..2e6dc5990ce 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include #include #include @@ -163,11 +163,7 @@ static DECLARE_MUTEX(nodemgr_serialize); struct host_info { struct hpsb_host *host; struct list_head list; - struct completion exited; - struct semaphore reset_sem; - int pid; - char daemon_name[15]; - int kill_me; + struct task_struct *thread; }; static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); @@ -1477,9 +1473,8 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) /* If we had a bus reset while we were scanning the bus, it is * possible that we did not probe all nodes. In that case, we * skip the clean up for now, since we could remove nodes that - * were still on the bus. The bus reset increased hi->reset_sem, - * so there's a bus scan pending which will do the clean up - * eventually. + * were still on the bus. Another bus scan is pending which will + * do the clean up eventually. * * Now let's tell the bus to rescan our devices. This may seem * like overhead, but the driver-model core will only scan a @@ -1607,41 +1602,37 @@ static int nodemgr_host_thread(void *__hi) { struct host_info *hi = (struct host_info *)__hi; struct hpsb_host *host = hi->host; - int reset_cycles = 0; - - /* No userlevel access needed */ - daemonize(hi->daemon_name); + unsigned int g, generation = get_hpsb_generation(host) - 1; + int i, reset_cycles = 0; /* Setup our device-model entries */ nodemgr_create_host_dev_files(host); - /* Sit and wait for a signal to probe the nodes on the bus. This - * happens when we get a bus reset. */ - while (1) { - unsigned int generation = 0; - int i; + for (;;) { + /* Sleep until next bus reset */ + set_current_state(TASK_INTERRUPTIBLE); + if (get_hpsb_generation(host) == generation) + schedule(); + __set_current_state(TASK_RUNNING); + + /* Thread may have been woken up to freeze or to exit */ + if (try_to_freeze()) + continue; + if (kthread_should_stop()) + goto exit; - if (down_interruptible(&hi->reset_sem) || - down_interruptible(&nodemgr_serialize)) { + if (down_interruptible(&nodemgr_serialize)) { if (try_to_freeze()) continue; - printk("NodeMgr: received unexpected signal?!\n" ); - break; - } - - if (hi->kill_me) { - up(&nodemgr_serialize); - break; + goto exit; } /* Pause for 1/4 second in 1/16 second intervals, * to make sure things settle down. */ + g = get_hpsb_generation(host); for (i = 0; i < 4 ; i++) { - set_current_state(TASK_INTERRUPTIBLE); - if (msleep_interruptible(63)) { - up(&nodemgr_serialize); - goto caught_signal; - } + if (msleep_interruptible(63) || kthread_should_stop()) + goto unlock_exit; /* Now get the generation in which the node ID's we collect * are valid. During the bus scan we will use this generation @@ -1652,14 +1643,8 @@ static int nodemgr_host_thread(void *__hi) /* If we get a reset before we are done waiting, then * start the the waiting over again */ - while (!down_trylock(&hi->reset_sem)) - i = 0; - - /* Check the kill_me again */ - if (hi->kill_me) { - up(&nodemgr_serialize); - goto caught_signal; - } + if (generation != g) + g = generation, i = 0; } if (!nodemgr_check_irm_capability(host, reset_cycles) || @@ -1685,11 +1670,11 @@ static int nodemgr_host_thread(void *__hi) up(&nodemgr_serialize); } - -caught_signal: +unlock_exit: + up(&nodemgr_serialize); +exit: HPSB_VERBOSE("NodeMgr: Exiting thread"); - - complete_and_exit(&hi->exited, 0); + return 0; } int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *)) @@ -1749,41 +1734,27 @@ static void nodemgr_add_host(struct hpsb_host *host) struct host_info *hi; hi = hpsb_create_hostinfo(&nodemgr_highlevel, host, sizeof(*hi)); - if (!hi) { - HPSB_ERR ("NodeMgr: out of memory in add host"); + HPSB_ERR("NodeMgr: out of memory in add host"); return; } - hi->host = host; - init_completion(&hi->exited); - sema_init(&hi->reset_sem, 0); - - sprintf(hi->daemon_name, "knodemgrd_%d", host->id); - - hi->pid = kernel_thread(nodemgr_host_thread, hi, CLONE_KERNEL); - - if (hi->pid < 0) { - HPSB_ERR ("NodeMgr: failed to start %s thread for %s", - hi->daemon_name, host->driver->name); + hi->thread = kthread_run(nodemgr_host_thread, hi, "knodemgrd_%d", + host->id); + if (IS_ERR(hi->thread)) { + HPSB_ERR("NodeMgr: cannot start thread for host %d", host->id); hpsb_destroy_hostinfo(&nodemgr_highlevel, host); - return; } - - return; } static void nodemgr_host_reset(struct hpsb_host *host) { struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host); - if (hi != NULL) { - HPSB_VERBOSE("NodeMgr: Processing host reset for %s", hi->daemon_name); - up(&hi->reset_sem); - } else - HPSB_ERR ("NodeMgr: could not process reset of unused host"); - - return; + if (hi) { + HPSB_VERBOSE("NodeMgr: Processing reset for host %d", host->id); + wake_up_process(hi->thread); + } } static void nodemgr_remove_host(struct hpsb_host *host) @@ -1791,18 +1762,9 @@ static void nodemgr_remove_host(struct hpsb_host *host) struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host); if (hi) { - if (hi->pid >= 0) { - hi->kill_me = 1; - mb(); - up(&hi->reset_sem); - wait_for_completion(&hi->exited); - nodemgr_remove_host_dev(&host->device); - } - } else - HPSB_ERR("NodeMgr: host %s does not exist, cannot remove", - host->driver->name); - - return; + kthread_stop(hi->thread); + nodemgr_remove_host_dev(&host->device); + } } static struct hpsb_highlevel nodemgr_highlevel = { -- cgit v1.2.3 From cab8d154e2ed43fe1495aa0e18103e747552891b Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:36 -0400 Subject: [PATCH] ieee1394: nodemgr: convert nodemgr_serialize semaphore to mutex Another trivial sem2mutex conversion. Side note: nodemgr_serialize's purpose, when introduced in linux1394's revision 529 in July 2002, was to protect several data structures which are now largely handled by or together with Linux' driver core and are now protected by the LDM's own mechanisms. It may very well be possible to remove this mutex now. But fully parallelized node scanning is on our long-term TODO list anyway; the mutex will certainly go away then. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/nodemgr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 2e6dc5990ce..f8f6079cc48 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -158,7 +158,7 @@ static struct csr1212_bus_ops nodemgr_csr_ops = { * but now we are much simpler because of the LDM. */ -static DECLARE_MUTEX(nodemgr_serialize); +static DEFINE_MUTEX(nodemgr_serialize); struct host_info { struct hpsb_host *host; @@ -1621,7 +1621,7 @@ static int nodemgr_host_thread(void *__hi) if (kthread_should_stop()) goto exit; - if (down_interruptible(&nodemgr_serialize)) { + if (mutex_lock_interruptible(&nodemgr_serialize)) { if (try_to_freeze()) continue; goto exit; @@ -1650,7 +1650,7 @@ static int nodemgr_host_thread(void *__hi) if (!nodemgr_check_irm_capability(host, reset_cycles) || !nodemgr_do_irm_duties(host, reset_cycles)) { reset_cycles++; - up(&nodemgr_serialize); + mutex_unlock(&nodemgr_serialize); continue; } reset_cycles = 0; @@ -1668,10 +1668,10 @@ static int nodemgr_host_thread(void *__hi) /* Update some of our sysfs symlinks */ nodemgr_update_host_dev_links(host); - up(&nodemgr_serialize); + mutex_unlock(&nodemgr_serialize); } unlock_exit: - up(&nodemgr_serialize); + mutex_unlock(&nodemgr_serialize); exit: HPSB_VERBOSE("NodeMgr: Exiting thread"); return 0; -- cgit v1.2.3 From 3c6c65f5ed5a6d307bd607aecd06d658c0934d88 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 3 Jul 2006 12:02:37 -0400 Subject: [PATCH] ieee1394: fix kerneldoc of hpsb_alloc_host There was stuff between the comment and the function. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins --- drivers/ieee1394/hosts.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index 2c669287f5b..3ed56be8706 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c @@ -90,6 +90,8 @@ static int alloc_hostnum_cb(struct hpsb_host *host, void *__data) return 0; } +static DEFINE_MUTEX(host_num_alloc); + /** * hpsb_alloc_host - allocate a new host controller. * @drv: the driver that will manage the host controller @@ -105,8 +107,6 @@ static int alloc_hostnum_cb(struct hpsb_host *host, void *__data) * Return Value: a pointer to the &hpsb_host if successful, %NULL if * no memory was available. */ -static DEFINE_MUTEX(host_num_alloc); - struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, struct device *dev) { -- cgit v1.2.3 From 9951903e616662e9a5dad5fbd296690e2ebbbc65 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 2 Jul 2006 14:17:00 +0200 Subject: ieee1394: shrink tlabel pools, remove tpool semaphores This patch reduces the size of struct hpsb_host and also removes semaphores from ieee1394_transactions.c. On i386, struct hpsb_host shrinks from 10656 bytes to 6688 bytes. This is accomplished by - using a single wait_queue for hpsb_get_tlabel instead of many instances of semaphores, - using a single lock to serialize access to all tlabel pools (the protected code regions are small, i.e. lock contention very low), - omitting the sysfs attribute tlabels_allocations. Drawback: In the rare case that a process needs to sleep because all transaction labels for the node are temporarily exhausted, it is also woken up if a tlabel for a different node became free, checks for an available tlabel, and is put to sleep again. The check is not costly and the situation occurs extremely rarely. (Tlabels are typically only exhausted if there was no context switch to the khpsbpkt thread which recycles tlables.) Therefore the benefit of reduced tpool size outweighs this drawback. The sysfs attributes tlabels_free and tlabels_mask are not compiled anymore unless CONFIG_IEEE1394_VERBOSEDEBUG is set. The by far biggest member of struct hpsb_host, the struct csr_control csr (5272 bytes on i386), is now placed at the end of struct hpsb_host. Note, hpsb_get_tlabel calls the macro wait_event_interruptible with a condition argument which has a side effect (allocation of a tlabel and manipulation of the packet). This side effect happens only if the condition is true. The patch relies on wait_event_interruptible not evaluating the condition again after it became true. Signed-off-by: Stefan Richter --- drivers/ieee1394/hosts.c | 3 - drivers/ieee1394/hosts.h | 19 +++--- drivers/ieee1394/ieee1394_transactions.c | 108 ++++++++++++++++++------------- drivers/ieee1394/ieee1394_transactions.h | 4 ++ drivers/ieee1394/ieee1394_types.h | 23 +------ drivers/ieee1394/nodemgr.c | 43 +++++++----- drivers/ieee1394/nodemgr.h | 1 - 7 files changed, 102 insertions(+), 99 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index 59e6f49545b..d90a3a1898c 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c @@ -143,9 +143,6 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, for (i = 2; i < 16; i++) h->csr.gen_timestamp[i] = jiffies - 60 * HZ; - for (i = 0; i < ARRAY_SIZE(h->tpool); i++) - HPSB_TPOOL_INIT(&h->tpool[i]); - atomic_set(&h->generation, 0); INIT_WORK(&h->delayed_reset, delayed_reset_bus, h); diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index 69a7c9ff5ed..bc6dbfadb89 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h @@ -35,7 +35,6 @@ struct hpsb_host { int node_count; /* number of identified nodes on this bus */ int selfid_count; /* total number of SelfIDs received */ int nodes_active; /* number of nodes with active link layer */ - u8 speed[ALL_NODES]; /* speed between each node and local node */ nodeid_t node_id; /* node ID of this host */ nodeid_t irm_id; /* ID of this bus' isochronous resource manager */ @@ -55,31 +54,29 @@ struct hpsb_host { int reset_retries; quadlet_t *topology_map; u8 *speed_map; - struct csr_control csr; - - /* Per node tlabel pool allocation */ - struct hpsb_tlabel_pool tpool[ALL_NODES]; + int id; struct hpsb_host_driver *driver; - struct pci_dev *pdev; - - int id; - struct device device; struct class_device class_dev; int update_config_rom; struct work_struct delayed_reset; - unsigned int config_roms; struct list_head addr_space; u64 low_addr_space; /* upper bound of physical DMA area */ u64 middle_addr_space; /* upper bound of posted write area */ -}; + u8 speed[ALL_NODES]; /* speed between each node and local node */ + /* per node tlabel allocation */ + u8 next_tl[ALL_NODES]; + struct { DECLARE_BITMAP(map, 64); } tl_pool[ALL_NODES]; + + struct csr_control csr; +}; enum devctl_cmd { /* Host is requested to reset its bus and cancel all outstanding async diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c index 751960037e2..0833fc9f50c 100644 --- a/drivers/ieee1394/ieee1394_transactions.c +++ b/drivers/ieee1394/ieee1394_transactions.c @@ -9,10 +9,9 @@ * directory of the kernel sources for details. */ -#include #include -#include -#include +#include +#include #include #include @@ -21,8 +20,6 @@ #include "ieee1394_types.h" #include "hosts.h" #include "ieee1394_core.h" -#include "highlevel.h" -#include "nodemgr.h" #include "ieee1394_transactions.h" #define PREP_ASYNC_HEAD_ADDRESS(tc) \ @@ -32,6 +29,13 @@ packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \ packet->header[2] = addr & 0xffffffff +#ifndef HPSB_DEBUG_TLABELS +static +#endif +spinlock_t hpsb_tlabel_lock = SPIN_LOCK_UNLOCKED; + +static DECLARE_WAIT_QUEUE_HEAD(tlabel_wq); + static void fill_async_readquad(struct hpsb_packet *packet, u64 addr) { PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ); @@ -115,9 +119,41 @@ static void fill_async_stream_packet(struct hpsb_packet *packet, int length, packet->tcode = TCODE_ISO_DATA; } +/* same as hpsb_get_tlabel, except that it returns immediately */ +static int hpsb_get_tlabel_atomic(struct hpsb_packet *packet) +{ + unsigned long flags, *tp; + u8 *next; + int tlabel, n = NODEID_TO_NODE(packet->node_id); + + /* Broadcast transactions are complete once the request has been sent. + * Use the same transaction label for all broadcast transactions. */ + if (unlikely(n == ALL_NODES)) { + packet->tlabel = 0; + return 0; + } + tp = packet->host->tl_pool[n].map; + next = &packet->host->next_tl[n]; + + spin_lock_irqsave(&hpsb_tlabel_lock, flags); + tlabel = find_next_zero_bit(tp, 64, *next); + if (tlabel > 63) + tlabel = find_first_zero_bit(tp, 64); + if (tlabel > 63) { + spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); + return -EAGAIN; + } + __set_bit(tlabel, tp); + *next = (tlabel + 1) & 63; + spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); + + packet->tlabel = tlabel; + return 0; +} + /** * hpsb_get_tlabel - allocate a transaction label - * @packet: the packet who's tlabel/tpool we set + * @packet: the packet whose tlabel and tl_pool we set * * Every asynchronous transaction on the 1394 bus needs a transaction * label to match the response to the request. This label has to be @@ -131,42 +167,25 @@ static void fill_async_stream_packet(struct hpsb_packet *packet, int length, * Return value: Zero on success, otherwise non-zero. A non-zero return * generally means there are no available tlabels. If this is called out * of interrupt or atomic context, then it will sleep until can return a - * tlabel. + * tlabel or a signal is received. */ int hpsb_get_tlabel(struct hpsb_packet *packet) { - unsigned long flags; - struct hpsb_tlabel_pool *tp; - int n = NODEID_TO_NODE(packet->node_id); - - if (unlikely(n == ALL_NODES)) - return 0; - tp = &packet->host->tpool[n]; - - if (irqs_disabled() || in_atomic()) { - if (down_trylock(&tp->count)) - return 1; - } else { - down(&tp->count); - } - - spin_lock_irqsave(&tp->lock, flags); - - packet->tlabel = find_next_zero_bit(tp->pool, 64, tp->next); - if (packet->tlabel > 63) - packet->tlabel = find_first_zero_bit(tp->pool, 64); - tp->next = (packet->tlabel + 1) % 64; - /* Should _never_ happen */ - BUG_ON(test_and_set_bit(packet->tlabel, tp->pool)); - tp->allocations++; - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; + if (irqs_disabled() || in_atomic()) + return hpsb_get_tlabel_atomic(packet); + + /* NB: The macro wait_event_interruptible() is called with a condition + * argument with side effect. This is only possible because the side + * effect does not occur until the condition became true, and + * wait_event_interruptible() won't evaluate the condition again after + * that. */ + return wait_event_interruptible(tlabel_wq, + !hpsb_get_tlabel_atomic(packet)); } /** * hpsb_free_tlabel - free an allocated transaction label - * @packet: packet whos tlabel/tpool needs to be cleared + * @packet: packet whose tlabel and tl_pool needs to be cleared * * Frees the transaction label allocated with hpsb_get_tlabel(). The * tlabel has to be freed after the transaction is complete (i.e. response @@ -177,21 +196,20 @@ int hpsb_get_tlabel(struct hpsb_packet *packet) */ void hpsb_free_tlabel(struct hpsb_packet *packet) { - unsigned long flags; - struct hpsb_tlabel_pool *tp; - int n = NODEID_TO_NODE(packet->node_id); + unsigned long flags, *tp; + int tlabel, n = NODEID_TO_NODE(packet->node_id); if (unlikely(n == ALL_NODES)) return; - tp = &packet->host->tpool[n]; - - BUG_ON(packet->tlabel > 63 || packet->tlabel < 0); + tp = packet->host->tl_pool[n].map; + tlabel = packet->tlabel; + BUG_ON(tlabel > 63 || tlabel < 0); - spin_lock_irqsave(&tp->lock, flags); - BUG_ON(!test_and_clear_bit(packet->tlabel, tp->pool)); - spin_unlock_irqrestore(&tp->lock, flags); + spin_lock_irqsave(&hpsb_tlabel_lock, flags); + BUG_ON(!__test_and_clear_bit(tlabel, tp)); + spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); - up(&tp->count); + wake_up_interruptible(&tlabel_wq); } int hpsb_packet_success(struct hpsb_packet *packet) diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h index 290d37060b0..c1369c41469 100644 --- a/drivers/ieee1394/ieee1394_transactions.h +++ b/drivers/ieee1394/ieee1394_transactions.h @@ -53,4 +53,8 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation, int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation, u64 addr, quadlet_t *buffer, size_t length); +#ifdef HPSB_DEBUG_TLABELS +extern spinlock_t hpsb_tlabel_lock; +#endif + #endif /* _IEEE1394_TRANSACTIONS_H */ diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h index 16fd2d0b5ed..a8de375e79b 100644 --- a/drivers/ieee1394/ieee1394_types.h +++ b/drivers/ieee1394/ieee1394_types.h @@ -2,31 +2,9 @@ #define _IEEE1394_TYPES_H #include -#include -#include #include #include - #include -#include - -/* Transaction Label handling */ -struct hpsb_tlabel_pool { - DECLARE_BITMAP(pool, 64); - spinlock_t lock; - u8 next; - u32 allocations; - struct semaphore count; -}; - -#define HPSB_TPOOL_INIT(_tp) \ -do { \ - bitmap_zero((_tp)->pool, 64); \ - spin_lock_init(&(_tp)->lock); \ - (_tp)->next = 0; \ - (_tp)->allocations = 0; \ - sema_init(&(_tp)->count, 63); \ -} while (0) typedef u32 quadlet_t; typedef u64 octlet_t; @@ -61,6 +39,7 @@ typedef u16 arm_length_t; #ifdef CONFIG_IEEE1394_VERBOSEDEBUG #define HPSB_VERBOSE(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args) +#define HPSB_DEBUG_TLABELS #else #define HPSB_VERBOSE(fmt, args...) #endif diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index f8f6079cc48..eabc51b23c0 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -327,34 +327,44 @@ static ssize_t fw_show_ne_bus_options(struct device *dev, struct device_attribut static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL); -/* tlabels_free, tlabels_allocations, tlabels_mask are read non-atomically - * here, therefore displayed values may be occasionally wrong. */ -static ssize_t fw_show_ne_tlabels_free(struct device *dev, struct device_attribute *attr, char *buf) +#ifdef HPSB_DEBUG_TLABELS +static ssize_t fw_show_ne_tlabels_free(struct device *dev, + struct device_attribute *attr, char *buf) { struct node_entry *ne = container_of(dev, struct node_entry, device); - return sprintf(buf, "%d\n", 64 - bitmap_weight(ne->tpool->pool, 64)); -} -static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL); + unsigned long flags; + unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map; + int tf; + spin_lock_irqsave(&hpsb_tlabel_lock, flags); + tf = 64 - bitmap_weight(tp, 64); + spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); -static ssize_t fw_show_ne_tlabels_allocations(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct node_entry *ne = container_of(dev, struct node_entry, device); - return sprintf(buf, "%u\n", ne->tpool->allocations); + return sprintf(buf, "%d\n", tf); } -static DEVICE_ATTR(tlabels_allocations,S_IRUGO,fw_show_ne_tlabels_allocations,NULL); +static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL); -static ssize_t fw_show_ne_tlabels_mask(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t fw_show_ne_tlabels_mask(struct device *dev, + struct device_attribute *attr, char *buf) { struct node_entry *ne = container_of(dev, struct node_entry, device); + unsigned long flags; + unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map; + u64 tm; + + spin_lock_irqsave(&hpsb_tlabel_lock, flags); #if (BITS_PER_LONG <= 32) - return sprintf(buf, "0x%08lx%08lx\n", ne->tpool->pool[0], ne->tpool->pool[1]); + tm = ((u64)tp[0] << 32) + tp[1]; #else - return sprintf(buf, "0x%016lx\n", ne->tpool->pool[0]); + tm = tp[0]; #endif + spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); + + return sprintf(buf, "0x%016llx\n", tm); } static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL); +#endif /* HPSB_DEBUG_TLABELS */ static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -461,9 +471,10 @@ static struct device_attribute *const fw_ne_attrs[] = { &dev_attr_ne_vendor_id, &dev_attr_ne_nodeid, &dev_attr_bus_options, +#ifdef HPSB_DEBUG_TLABELS &dev_attr_tlabels_free, - &dev_attr_tlabels_allocations, &dev_attr_tlabels_mask, +#endif }; @@ -782,8 +793,6 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr if (!ne) return NULL; - ne->tpool = &host->tpool[nodeid & NODE_MASK]; - ne->host = host; ne->nodeid = nodeid; ne->generation = generation; diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h index f649c9d321b..0e1e7d93078 100644 --- a/drivers/ieee1394/nodemgr.h +++ b/drivers/ieee1394/nodemgr.h @@ -107,7 +107,6 @@ struct node_entry { const char *vendor_oui; u32 capabilities; - struct hpsb_tlabel_pool *tpool; struct device device; struct class_device class_dev; -- cgit v1.2.3 From 9154df538fa044ac2b729ae5c6c47cae09e6977f Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 23 Jul 2006 22:01:00 +0200 Subject: ieee1394: remove #include These includes in ieee1394_core and eth1394 are obsolete. Signed-off-by: Stefan Richter --- drivers/ieee1394/eth1394.c | 1 - drivers/ieee1394/ieee1394_core.c | 1 - drivers/ieee1394/ieee1394_core.h | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 09826be86aa..8a7b8fab623 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -64,7 +64,6 @@ #include #include #include -#include #include #include "config_roms.h" diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index 559c477092f..e4dd5bc3fb7 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -35,7 +35,6 @@ #include #include -#include #include "ieee1394_types.h" #include "ieee1394.h" diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h index 1ce172b2856..af4a78a8ef3 100644 --- a/drivers/ieee1394/ieee1394_core.h +++ b/drivers/ieee1394/ieee1394_core.h @@ -7,7 +7,6 @@ #include #include #include -#include #include "hosts.h" #include "ieee1394_types.h" -- cgit v1.2.3 From cc078189125db84a85a3bbb82df788b84fc68aa1 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 23 Jul 2006 22:12:00 +0200 Subject: ieee1394: sbp2: safer last_orb and next_ORB handling The sbp2 initiator has two ways to tell a target's fetch agent about new command ORBs: - Write the ORB's address to the ORB_POINTER register. This must not be done while the fetch agent is active. - Put the ORB's address into the previously submitted ORB's next_ORB field and write to the DOORBELL register. This may be done while the fetch agent is active or suspended. It must not be done while the fetch agent is in reset state. Sbp2 has a last_orb pointer which indicates in what way a new command should be announced. That pointer is concurrently accessed at various occasions. Furthermore, initiator and target are accessing the next_ORB field of ORBs concurrently and asynchronously. This patch does: - Protect all initiator accesses to last_orb by sbp2_command_orb_lock. - Add pci_dma_sync_single_for_device before a previously submitted ORB's next_ORB field is overwritten. - Insert a memory barrier between when next_ORB_lo and next_ORB_hi are overwritten. Next_ORB_hi must not be updated before next_ORB_lo. - Remove the rather unspecific and now superfluous qualifier "volatile" from the next_ORB fields. - Add comments on how last_orb is connected with what is known about the target's fetch agent's state. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 101 +++++++++++++++++++++++------------------------- drivers/ieee1394/sbp2.h | 4 +- 2 files changed, 50 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index baa063c9e6e..e312d5e2a64 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -1705,6 +1705,7 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait) quadlet_t data; u64 addr; int retval; + unsigned long flags; SBP2_DEBUG_ENTER(); @@ -1724,7 +1725,9 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait) /* * Need to make sure orb pointer is written on next command */ + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); scsi_id->last_orb = NULL; + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return 0; } @@ -1966,8 +1969,12 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, { struct sbp2scsi_host_info *hi = scsi_id->hi; struct sbp2_command_orb *command_orb = &command->command_orb; - struct node_entry *ne = scsi_id->ne; - u64 addr; + struct sbp2_command_orb *last_orb; + dma_addr_t last_orb_dma; + u64 addr = scsi_id->sbp2_command_block_agent_addr; + quadlet_t data[2]; + size_t length; + unsigned long flags; outstanding_orb_incr; SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x", @@ -1982,64 +1989,50 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, /* * Check to see if there are any previous orbs to use */ - if (scsi_id->last_orb == NULL) { - quadlet_t data[2]; - + spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); + last_orb = scsi_id->last_orb; + last_orb_dma = scsi_id->last_orb_dma; + if (!last_orb) { /* - * Ok, let's write to the target's management agent register + * last_orb == NULL means: We know that the target's fetch agent + * is not active right now. */ - addr = scsi_id->sbp2_command_block_agent_addr + SBP2_ORB_POINTER_OFFSET; + addr += SBP2_ORB_POINTER_OFFSET; data[0] = ORB_SET_NODE_ID(hi->host->node_id); data[1] = command->command_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); - - SBP2_ORB_DEBUG("write command agent, command orb %p", command_orb); - - if (sbp2util_node_write_no_wait(ne, addr, data, 8) < 0) { - SBP2_ERR("sbp2util_node_write_no_wait failed.\n"); - return -EIO; - } - - SBP2_ORB_DEBUG("write command agent complete"); - - scsi_id->last_orb = command_orb; - scsi_id->last_orb_dma = command->command_orb_dma; - + length = 8; } else { - quadlet_t data; - /* - * We have an orb already sent (maybe or maybe not - * processed) that we can append this orb to. So do so, - * and ring the doorbell. Have to be very careful - * modifying these next orb pointers, as they are accessed - * both by the sbp2 device and us. + * last_orb != NULL means: We know that the target's fetch agent + * is (very probably) not dead or in reset state right now. + * We have an ORB already sent that we can append a new one to. + * The target's fetch agent may or may not have read this + * previous ORB yet. */ - scsi_id->last_orb->next_ORB_lo = - cpu_to_be32(command->command_orb_dma); + pci_dma_sync_single_for_cpu(hi->host->pdev, last_orb_dma, + sizeof(struct sbp2_command_orb), + PCI_DMA_BIDIRECTIONAL); + last_orb->next_ORB_lo = cpu_to_be32(command->command_orb_dma); + wmb(); /* Tells hardware that this pointer is valid */ - scsi_id->last_orb->next_ORB_hi = 0x0; - pci_dma_sync_single_for_device(hi->host->pdev, - scsi_id->last_orb_dma, + last_orb->next_ORB_hi = 0; + pci_dma_sync_single_for_device(hi->host->pdev, last_orb_dma, sizeof(struct sbp2_command_orb), PCI_DMA_BIDIRECTIONAL); + addr += SBP2_DOORBELL_OFFSET; + data[0] = 0; + length = 4; + } + scsi_id->last_orb = command_orb; + scsi_id->last_orb_dma = command->command_orb_dma; + spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); - /* - * Ring the doorbell - */ - data = cpu_to_be32(command->command_orb_dma); - addr = scsi_id->sbp2_command_block_agent_addr + SBP2_DOORBELL_OFFSET; - - SBP2_ORB_DEBUG("ring doorbell, command orb %p", command_orb); - - if (sbp2util_node_write_no_wait(ne, addr, &data, 4) < 0) { - SBP2_ERR("sbp2util_node_write_no_wait failed"); - return -EIO; - } - - scsi_id->last_orb = command_orb; - scsi_id->last_orb_dma = command->command_orb_dma; - + SBP2_ORB_DEBUG("write to %s register, command orb %p", + last_orb ? "DOORBELL" : "ORB_POINTER", command_orb); + if (sbp2util_node_write_no_wait(scsi_id->ne, addr, data, length) < 0) { + SBP2_ERR("sbp2util_node_write_no_wait failed.\n"); + return -EIO; } return 0; } @@ -2231,14 +2224,16 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest } /* - * Check here to see if there are no commands in-use. If there are none, we can - * null out last orb so that next time around we write directly to the orb pointer... - * Quick start saves one 1394 bus transaction. + * Check here to see if there are no commands in-use. If there + * are none, we know that the fetch agent left the active state + * _and_ that we did not reactivate it yet. Therefore clear + * last_orb so that next time we write directly to the + * ORB_POINTER register. That way the fetch agent does not need + * to refetch the next_ORB. */ spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); - if (list_empty(&scsi_id->sbp2_command_orb_inuse)) { + if (list_empty(&scsi_id->sbp2_command_orb_inuse)) scsi_id->last_orb = NULL; - } spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); } else { diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index b22ce1aa8fe..dd80906e8a9 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -46,8 +46,8 @@ #define ORB_SET_DIRECTION(value) ((value & 0x1) << 27) struct sbp2_command_orb { - volatile u32 next_ORB_hi; - volatile u32 next_ORB_lo; + u32 next_ORB_hi; + u32 next_ORB_lo; u32 data_descriptor_hi; u32 data_descriptor_lo; u32 misc; -- cgit v1.2.3 From 28212767e58402ea362edcb80b753d49bfd44d98 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 23 Jul 2006 22:10:00 +0200 Subject: ieee1394: sbp2: discard return value of sbp2_link_orb_command Since sbp2 is at the moment unable to do anything with the return value of sbp2_link_orb_command, just discard it. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 8 +++----- drivers/ieee1394/sbp2.h | 5 ----- 2 files changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index e312d5e2a64..670a13981fd 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -1964,7 +1964,7 @@ static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id, /* * This function is called in order to begin a regular SBP-2 command. */ -static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, +static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command) { struct sbp2scsi_host_info *hi = scsi_id->hi; @@ -2030,11 +2030,9 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, SBP2_ORB_DEBUG("write to %s register, command orb %p", last_orb ? "DOORBELL" : "ORB_POINTER", command_orb); - if (sbp2util_node_write_no_wait(scsi_id->ne, addr, data, length) < 0) { + if (sbp2util_node_write_no_wait(scsi_id->ne, addr, data, length)) SBP2_ERR("sbp2util_node_write_no_wait failed.\n"); - return -EIO; - } - return 0; + /* We rely on SCSI EH to deal with _node_write_ failures. */ } /* diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index dd80906e8a9..b17016b7cfc 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -390,11 +390,6 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id); static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data, u64 addr, size_t length, u16 flags); static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait); -static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, - struct sbp2_command_info *command); -static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, - struct scsi_cmnd *SCpnt, - void (*done)(struct scsi_cmnd *)); static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data); static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, -- cgit v1.2.3 From d4018d7fa63d25f3e1ecf6949fca6b81a182231a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 23 Jul 2006 22:57:00 +0200 Subject: ieee1394: sbp2: optimize DMA direction of command ORBs Only the driver writes ORBs, the device just reads them. Therefore PCI_DMA_BIDIRECTIONAL can be replaced by PCI_DMA_TODEVICE which may be cheaper on some architectures. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 670a13981fd..11595df8b75 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -492,7 +492,7 @@ static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_i command->command_orb_dma = pci_map_single(hi->host->pdev, &command->command_orb, sizeof(struct sbp2_command_orb), - PCI_DMA_BIDIRECTIONAL); + PCI_DMA_TODEVICE); SBP2_DMA_ALLOC("single command orb DMA"); command->sge_dma = pci_map_single(hi->host->pdev, @@ -525,7 +525,7 @@ static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_ /* Release our generic DMA's */ pci_unmap_single(host->pdev, command->command_orb_dma, sizeof(struct sbp2_command_orb), - PCI_DMA_BIDIRECTIONAL); + PCI_DMA_TODEVICE); SBP2_DMA_FREE("single command orb DMA"); pci_unmap_single(host->pdev, command->sge_dma, sizeof(command->scatter_gather_element), @@ -1982,7 +1982,7 @@ static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, pci_dma_sync_single_for_device(hi->host->pdev, command->command_orb_dma, sizeof(struct sbp2_command_orb), - PCI_DMA_BIDIRECTIONAL); + PCI_DMA_TODEVICE); pci_dma_sync_single_for_device(hi->host->pdev, command->sge_dma, sizeof(command->scatter_gather_element), PCI_DMA_BIDIRECTIONAL); @@ -2012,14 +2012,14 @@ static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, */ pci_dma_sync_single_for_cpu(hi->host->pdev, last_orb_dma, sizeof(struct sbp2_command_orb), - PCI_DMA_BIDIRECTIONAL); + PCI_DMA_TODEVICE); last_orb->next_ORB_lo = cpu_to_be32(command->command_orb_dma); wmb(); /* Tells hardware that this pointer is valid */ last_orb->next_ORB_hi = 0; pci_dma_sync_single_for_device(hi->host->pdev, last_orb_dma, sizeof(struct sbp2_command_orb), - PCI_DMA_BIDIRECTIONAL); + PCI_DMA_TODEVICE); addr += SBP2_DOORBELL_OFFSET; data[0] = 0; length = 4; @@ -2176,7 +2176,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest SBP2_DEBUG("Found status for command ORB"); pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma, sizeof(struct sbp2_command_orb), - PCI_DMA_BIDIRECTIONAL); + PCI_DMA_TODEVICE); pci_dma_sync_single_for_cpu(hi->host->pdev, command->sge_dma, sizeof(command->scatter_gather_element), PCI_DMA_BIDIRECTIONAL); @@ -2365,7 +2365,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id command = list_entry(lh, struct sbp2_command_info, list); pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma, sizeof(struct sbp2_command_orb), - PCI_DMA_BIDIRECTIONAL); + PCI_DMA_TODEVICE); pci_dma_sync_single_for_cpu(hi->host->pdev, command->sge_dma, sizeof(command->scatter_gather_element), PCI_DMA_BIDIRECTIONAL); @@ -2548,7 +2548,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma, sizeof(struct sbp2_command_orb), - PCI_DMA_BIDIRECTIONAL); + PCI_DMA_TODEVICE); pci_dma_sync_single_for_cpu(hi->host->pdev, command->sge_dma, sizeof(command->scatter_gather_element), -- cgit v1.2.3 From 3e98eab46d1a482532c653bdb0c006413654d171 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 23 Jul 2006 22:16:00 +0200 Subject: ieee1394: sbp2: safer initialization of status fifo Sbp2's copy of the status fifo was cleared when management ORBs or new command ORBs were prepared. The latter had potential for a race condition if the block layer's soft IRQ and the 1394 LLD's interrupt handler ran on different CPUs. It would also yield wrong status if a command was completed with non-zero completion status before other commands that had zero completion status, and no new command was enqueued in the meantime. Now, the status buffer is cleared right before it is written. Thus it ends up in the following simpler and safer access pattern: - sbp2_alloc_device: allocates and implicitly clears once, - sbp2_handle_status_write: clears, writes, and reads, - sbp2_query_logins, sbp2_login_device, sbp2_reconnect_device: read. The latter three do not race with sbp2_handle_status_write because of how the protocol works. As a tiny optimization, the first two quadlets of the status never need to be cleared. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 80 +++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 11595df8b75..c6776909747 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -1182,7 +1182,6 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) "sbp2 query logins orb", scsi_id->query_logins_orb_dma); memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response)); - memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block)); data[0] = ORB_SET_NODE_ID(hi->host->node_id); data[1] = scsi_id->query_logins_orb_dma; @@ -1278,7 +1277,6 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) "sbp2 login orb", scsi_id->login_orb_dma); memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response)); - memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block)); data[0] = ORB_SET_NODE_ID(hi->host->node_id); data[1] = scsi_id->login_orb_dma; @@ -1445,14 +1443,6 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) sbp2util_packet_dump(scsi_id->reconnect_orb, sizeof(struct sbp2_reconnect_orb), "sbp2 reconnect orb", scsi_id->reconnect_orb_dma); - /* - * Initialize status fifo - */ - memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block)); - - /* - * Ok, let's write to the target's management agent register - */ data[0] = ORB_SET_NODE_ID(hi->host->node_id); data[1] = scsi_id->reconnect_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); @@ -2068,11 +2058,6 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, sbp2util_packet_dump(&command->command_orb, sizeof(struct sbp2_command_orb), "sbp2 command orb", command->command_orb_dma); - /* - * Initialize status fifo - */ - memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block)); - /* * Link up the orb, and ring the doorbell if needed */ @@ -2114,12 +2099,14 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense /* * This function deals with status writes from the SBP-2 device */ -static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid, - quadlet_t *data, u64 addr, size_t length, u16 fl) +static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, + int destid, quadlet_t *data, u64 addr, + size_t length, u16 fl) { struct sbp2scsi_host_info *hi; struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp; struct scsi_cmnd *SCpnt = NULL; + struct sbp2_status_block *sb; u32 scsi_status = SBP2_SCSI_STATUS_GOOD; struct sbp2_command_info *command; unsigned long flags; @@ -2158,19 +2145,21 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest } /* - * Put response into scsi_id status fifo... + * Put response into scsi_id status fifo buffer. The first two bytes + * come in big endian bit order. Often the target writes only a + * truncated status block, minimally the first two quadlets. The rest + * is implied to be zeros. */ - memcpy(&scsi_id->status_block, data, length); + sb = &scsi_id->status_block; + memset(sb->command_set_dependent, 0, sizeof(sb->command_set_dependent)); + memcpy(sb, data, length); + sbp2util_be32_to_cpu_buffer(sb, 8); /* - * Byte swap first two quadlets (8 bytes) of status for processing + * Handle command ORB status here if necessary. First, need to match + * status with command. */ - sbp2util_be32_to_cpu_buffer(&scsi_id->status_block, 8); - - /* - * Handle command ORB status here if necessary. First, need to match status with command. - */ - command = sbp2util_find_command_for_orb(scsi_id, scsi_id->status_block.ORB_offset_lo); + command = sbp2util_find_command_for_orb(scsi_id, sb->ORB_offset_lo); if (command) { SBP2_DEBUG("Found status for command ORB"); @@ -2185,7 +2174,8 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest outstanding_orb_decr; /* - * Matched status with command, now grab scsi command pointers and check status + * Matched status with command, now grab scsi command pointers + * and check status. */ SCpnt = command->Current_SCpnt; spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); @@ -2193,28 +2183,22 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); if (SCpnt) { - /* - * See if the target stored any scsi status information + * See if the target stored any scsi status information. */ - if (STATUS_GET_LENGTH(scsi_id->status_block.ORB_offset_hi_misc) > 1) { - /* - * Translate SBP-2 status to SCSI sense data - */ + if (STATUS_GET_LENGTH(sb->ORB_offset_hi_misc) > 1) { SBP2_DEBUG("CHECK CONDITION"); - scsi_status = sbp2_status_to_sense_data((unchar *)&scsi_id->status_block, SCpnt->sense_buffer); + scsi_status = sbp2_status_to_sense_data( + (unchar *)sb, SCpnt->sense_buffer); } /* - * Check to see if the dead bit is set. If so, we'll have to initiate - * a fetch agent reset. + * Check to see if the dead bit is set. If so, we'll + * have to initiate a fetch agent reset. */ - if (STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc)) { - - /* - * Initiate a fetch agent reset. - */ - SBP2_DEBUG("Dead bit set - initiating fetch agent reset"); + if (STATUS_GET_DEAD_BIT(sb->ORB_offset_hi_misc)) { + SBP2_DEBUG("Dead bit set - " + "initiating fetch agent reset"); sbp2_agent_reset(scsi_id, 0); } @@ -2235,21 +2219,17 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); } else { - /* * It's probably a login/logout/reconnect status. */ - if ((scsi_id->login_orb_dma == scsi_id->status_block.ORB_offset_lo) || - (scsi_id->query_logins_orb_dma == scsi_id->status_block.ORB_offset_lo) || - (scsi_id->reconnect_orb_dma == scsi_id->status_block.ORB_offset_lo) || - (scsi_id->logout_orb_dma == scsi_id->status_block.ORB_offset_lo)) { + if ((sb->ORB_offset_lo == scsi_id->reconnect_orb_dma) || + (sb->ORB_offset_lo == scsi_id->login_orb_dma) || + (sb->ORB_offset_lo == scsi_id->query_logins_orb_dma) || + (sb->ORB_offset_lo == scsi_id->logout_orb_dma)) atomic_set(&scsi_id->sbp2_login_complete, 1); - } } if (SCpnt) { - - /* Complete the SCSI command. */ SBP2_DEBUG("Completing SCSI command"); sbp2scsi_complete_command(scsi_id, scsi_status, SCpnt, command->Current_done); -- cgit v1.2.3 From 6065772d54a3b994b9b5d3df6413ec6a1c8c2ec1 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 23 Jul 2006 22:18:00 +0200 Subject: ieee1394: sbp2: more checks of status block - Add checks for the (very unlikely) cases that the target writes too little or too much status data or writes unsolicited status. - Indicate that these and similar conditions are unlikely(). - Check the 'resp' and 'sbp_status' fields for possible failure status. - Slightly optimize access macros for the status block bitfields. - Unify a few related log messages. TODO: Check if 'src'==1, then withhold the respective ORB from reuse until status for any subsequent ORB was received. This is an old bug whose fix requires more complex command queue handling. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 70 +++++++++++++++++++++---------------------------- drivers/ieee1394/sbp2.h | 14 +++++----- 2 files changed, 38 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index c6776909747..07030be0ef2 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -1201,11 +1201,8 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) return -EIO; } - if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) || - STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) || - STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) { - - SBP2_INFO("Error querying logins to SBP-2 device - timed out"); + if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) { + SBP2_INFO("Error querying logins to SBP-2 device - failed"); return -EIO; } @@ -1298,18 +1295,12 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) * Sanity. Make sure status returned matches login orb. */ if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) { - SBP2_ERR("Error logging into SBP-2 device - login timed-out"); + SBP2_ERR("Error logging into SBP-2 device - timed out"); return -EIO; } - /* - * Check status - */ - if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) || - STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) || - STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) { - - SBP2_ERR("Error logging into SBP-2 device - login failed"); + if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) { + SBP2_ERR("Error logging into SBP-2 device - failed"); return -EIO; } @@ -1333,9 +1324,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) scsi_id->sbp2_command_block_agent_addr &= 0x0000ffffffffffffULL; SBP2_INFO("Logged into SBP-2 device"); - return 0; - } /* @@ -1466,25 +1455,17 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) * Sanity. Make sure status returned matches reconnect orb. */ if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) { - SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out"); + SBP2_ERR("Error reconnecting to SBP-2 device - timed out"); return -EIO; } - /* - * Check status - */ - if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) || - STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) || - STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) { - - SBP2_ERR("Error reconnecting to SBP-2 device - reconnect failed"); + if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) { + SBP2_ERR("Error reconnecting to SBP-2 device - failed"); return -EIO; } HPSB_DEBUG("Reconnected to SBP-2 device"); - return 0; - } /* @@ -2115,18 +2096,19 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr); - if (!host) { + if (unlikely(length < 8 || length > sizeof(struct sbp2_status_block))) { + SBP2_ERR("Wrong size of status block"); + return RCODE_ADDRESS_ERROR; + } + if (unlikely(!host)) { SBP2_ERR("host is NULL - this is bad!"); return RCODE_ADDRESS_ERROR; } - hi = hpsb_get_hostinfo(&sbp2_highlevel, host); - - if (!hi) { + if (unlikely(!hi)) { SBP2_ERR("host info is NULL - this is bad!"); return RCODE_ADDRESS_ERROR; } - /* * Find our scsi_id structure by looking at the status fifo address * written to by the sbp2 device. @@ -2138,8 +2120,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, break; } } - - if (!scsi_id) { + if (unlikely(!scsi_id)) { SBP2_ERR("scsi_id is NULL - device is gone?"); return RCODE_ADDRESS_ERROR; } @@ -2156,12 +2137,14 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, sbp2util_be32_to_cpu_buffer(sb, 8); /* - * Handle command ORB status here if necessary. First, need to match - * status with command. + * Ignore unsolicited status. Handle command ORB status. */ - command = sbp2util_find_command_for_orb(scsi_id, sb->ORB_offset_lo); + if (unlikely(STATUS_GET_SRC(sb->ORB_offset_hi_misc) == 2)) + command = NULL; + else + command = sbp2util_find_command_for_orb(scsi_id, + sb->ORB_offset_lo); if (command) { - SBP2_DEBUG("Found status for command ORB"); pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma, sizeof(struct sbp2_command_orb), @@ -2177,16 +2160,23 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, * Matched status with command, now grab scsi command pointers * and check status. */ + /* + * FIXME: If the src field in the status is 1, the ORB DMA must + * not be reused until status for a subsequent ORB is received. + */ SCpnt = command->Current_SCpnt; spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); sbp2util_mark_command_completed(scsi_id, command); spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); if (SCpnt) { + if (STATUS_TEST_RS(sb->ORB_offset_hi_misc)) + scsi_status = + SBP2_SCSI_STATUS_COMMAND_TERMINATED; /* * See if the target stored any scsi status information. */ - if (STATUS_GET_LENGTH(sb->ORB_offset_hi_misc) > 1) { + if (STATUS_GET_LEN(sb->ORB_offset_hi_misc) > 1) { SBP2_DEBUG("CHECK CONDITION"); scsi_status = sbp2_status_to_sense_data( (unchar *)sb, SCpnt->sense_buffer); @@ -2196,7 +2186,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, * Check to see if the dead bit is set. If so, we'll * have to initiate a fetch agent reset. */ - if (STATUS_GET_DEAD_BIT(sb->ORB_offset_hi_misc)) { + if (STATUS_TEST_D(sb->ORB_offset_hi_misc)) { SBP2_DEBUG("Dead bit set - " "initiating fetch agent reset"); sbp2_agent_reset(scsi_id, 0); diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index b17016b7cfc..34e3d37fc79 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -180,12 +180,14 @@ struct sbp2_unrestricted_page_table { #define SBP2_SCSI_STATUS_SELECTION_TIMEOUT 0xff -#define STATUS_GET_ORB_OFFSET_HI(value) (value & 0xffff) -#define STATUS_GET_SBP_STATUS(value) ((value >> 16) & 0xff) -#define STATUS_GET_LENGTH(value) ((value >> 24) & 0x7) -#define STATUS_GET_DEAD_BIT(value) ((value >> 27) & 0x1) -#define STATUS_GET_RESP(value) ((value >> 28) & 0x3) -#define STATUS_GET_SRC(value) ((value >> 30) & 0x3) +#define STATUS_GET_SRC(value) (((value) >> 30) & 0x3) +#define STATUS_GET_LEN(value) (((value) >> 24) & 0x7) +#define STATUS_GET_ORB_OFFSET_HI(value) ((value) & 0x0000ffff) +#define STATUS_TEST_D(value) ((value) & 0x08000000) +/* test 'resp' | 'sbp2_status' */ +#define STATUS_TEST_RS(value) ((value) & 0x30ff0000) +/* test 'resp' | 'dead' | 'sbp2_status' */ +#define STATUS_TEST_RDS(value) ((value) & 0x38ff0000) struct sbp2_status_block { u32 ORB_offset_hi_misc; -- cgit v1.2.3 From e8398bb737ceadff8825aa98cb9f4a5e96857546 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 23 Jul 2006 22:19:00 +0200 Subject: ieee1394: sbp2: convert sbp2util_down_timeout to waitqueue The waitqueue API is used to replace a custom wait mechanism. Only one global waitqueue (instead of per-device waitqueues or completions) is added because there is usually just one waiter. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 51 +++++++++++++++++++++---------------------------- drivers/ieee1394/sbp2.h | 4 ++-- 2 files changed, 24 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 07030be0ef2..6adbe1c796c 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -55,12 +55,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -420,21 +420,23 @@ static void sbp2util_packet_dump(void *buffer, int length, char *dump_name, #define sbp2util_packet_dump(w,x,y,z) #endif +static DECLARE_WAIT_QUEUE_HEAD(access_wq); + /* - * Goofy routine that basically does a down_timeout function. + * Waits for completion of an SBP-2 access request. + * Returns nonzero if timed out or prematurely interrupted. */ -static int sbp2util_down_timeout(atomic_t *done, int timeout) +static int sbp2util_access_timeout(struct scsi_id_instance_data *scsi_id, + int timeout) { - int i; + long leftover = wait_event_interruptible_timeout( + access_wq, scsi_id->access_complete, timeout); - for (i = timeout; (i > 0 && atomic_read(done) == 0); i-= HZ/10) { - if (msleep_interruptible(100)) /* 100ms */ - return 1; - } - return (i > 0) ? 0 : 1; + scsi_id->access_complete = 0; + return leftover <= 0; } -/* Free's an allocated packet */ +/* Frees an allocated packet */ static void sbp2_free_packet(struct hpsb_packet *packet) { hpsb_free_tlabel(packet); @@ -794,7 +796,6 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud scsi_id->speed_code = IEEE1394_SPEED_100; scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100]; scsi_id->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE; - atomic_set(&scsi_id->sbp2_login_complete, 0); INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); INIT_LIST_HEAD(&scsi_id->scsi_list); @@ -1187,11 +1188,9 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) data[1] = scsi_id->query_logins_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); - atomic_set(&scsi_id->sbp2_login_complete, 0); - hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); - if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) { + if (sbp2util_access_timeout(scsi_id, 2*HZ)) { SBP2_INFO("Error querying logins to SBP-2 device - timed out"); return -EIO; } @@ -1279,15 +1278,13 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) data[1] = scsi_id->login_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); - atomic_set(&scsi_id->sbp2_login_complete, 0); - hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); /* * Wait for login status (up to 20 seconds)... */ - if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 20*HZ)) { - SBP2_ERR("Error logging into SBP-2 device - login timed-out"); + if (sbp2util_access_timeout(scsi_id, 20*HZ)) { + SBP2_ERR("Error logging into SBP-2 device - timed out"); return -EIO; } @@ -1374,21 +1371,17 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id) data[1] = scsi_id->logout_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); - atomic_set(&scsi_id->sbp2_login_complete, 0); - error = hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); if (error) return error; /* Wait for device to logout...1 second. */ - if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, HZ)) + if (sbp2util_access_timeout(scsi_id, HZ)) return -EIO; SBP2_INFO("Logged out of SBP-2 device"); - return 0; - } /* @@ -1436,8 +1429,6 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) data[1] = scsi_id->reconnect_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); - atomic_set(&scsi_id->sbp2_login_complete, 0); - error = hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); if (error) @@ -1446,8 +1437,8 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) /* * Wait for reconnect status (up to 1 second)... */ - if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, HZ)) { - SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out"); + if (sbp2util_access_timeout(scsi_id, HZ)) { + SBP2_ERR("Error reconnecting to SBP-2 device - timed out"); return -EIO; } @@ -2215,8 +2206,10 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, if ((sb->ORB_offset_lo == scsi_id->reconnect_orb_dma) || (sb->ORB_offset_lo == scsi_id->login_orb_dma) || (sb->ORB_offset_lo == scsi_id->query_logins_orb_dma) || - (sb->ORB_offset_lo == scsi_id->logout_orb_dma)) - atomic_set(&scsi_id->sbp2_login_complete, 1); + (sb->ORB_offset_lo == scsi_id->logout_orb_dma)) { + scsi_id->access_complete = 1; + wake_up_interruptible(&access_wq); + } } if (SCpnt) { diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index 34e3d37fc79..89098fe565e 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -320,9 +320,9 @@ struct scsi_id_instance_data { u64 status_fifo_addr; /* - * Variable used for logins, reconnects, logouts, query logins + * Waitqueue flag for logins, reconnects, logouts, query logins */ - atomic_t sbp2_login_complete; + int access_complete:1; /* * Pool of command orbs, so we can have more than overlapped command per id -- cgit v1.2.3 From 8df4083c5291b3647e0381d3c69ab2196f5dd3b7 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 27 Jul 2006 21:54:00 +0200 Subject: Initialize ieee1394 early when built in This makes debugging with firescope easier. Signed-off-by: Andi Kleen (original patch) Update: - no need for #ifdef MODULE - add comment in ieee1394_core, more verbose comment in ohci1394 Signed-off-by: Stefan Richter (update) --- drivers/ieee1394/ieee1394_core.c | 2 +- drivers/ieee1394/ohci1394.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index e4dd5bc3fb7..991c378496f 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -1170,7 +1170,7 @@ static void __exit ieee1394_cleanup(void) unregister_chrdev_region(IEEE1394_CORE_DEV, 256); } -module_init(ieee1394_init); +fs_initcall(ieee1394_init); /* same as ohci1394 */ module_exit(ieee1394_cleanup); /* Exported symbols */ diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index baa090d08d2..330dcf7c699 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -3719,5 +3719,7 @@ static int __init ohci1394_init(void) return pci_register_driver(&ohci1394_pci_driver); } -module_init(ohci1394_init); +/* Register before most other device drivers. + * Useful for remote debugging via physical DMA, e.g. using firescope. */ +fs_initcall(ohci1394_init); module_exit(ohci1394_cleanup); -- cgit v1.2.3 From a1b3206b362335f7986d1fab294c16148a8c50ab Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 29 Jul 2006 19:48:28 +0200 Subject: the scheduled removal of drivers/ieee1394/sbp2.c:force_inquiry_hack This patch contains the scheduled removal of the force_inquiry_hack module parameter. Signed-off-by: Adrian Bunk Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 6adbe1c796c..1c8ce7acba8 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -173,11 +173,6 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0" ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) ", or a combination)"); -/* legacy parameter */ -static int force_inquiry_hack; -module_param(force_inquiry_hack, int, 0644); -MODULE_PARM_DESC(force_inquiry_hack, "Deprecated, use 'workarounds'"); - /* * Export information about protocols/devices supported by this driver. */ @@ -1554,11 +1549,6 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, } workarounds = sbp2_default_workarounds; - if (force_inquiry_hack) { - SBP2_WARN("force_inquiry_hack is deprecated. " - "Use parameter 'workarounds' instead."); - workarounds |= SBP2_WORKAROUND_INQUIRY_36; - } if (!(workarounds & SBP2_WORKAROUND_OVERRIDE)) for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) { -- cgit v1.2.3 From 4b60912e52bc6ccdf587f2b92f3435ee2678d730 Mon Sep 17 00:00:00 2001 From: David Moore Date: Wed, 2 Aug 2006 01:00:00 +0200 Subject: video1394: add poll file operation support This patch adds support for the poll file operation to the video1394 driver. Signed-off-by: David Moore Signed-off-by: Stefan Richter --- drivers/ieee1394/video1394.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 6b5353d81ae..af78b840dc2 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -1181,7 +1181,8 @@ static int video1394_mmap(struct file *file, struct vm_area_struct *vma) lock_kernel(); if (ctx->current_ctx == NULL) { - PRINT(KERN_ERR, ctx->ohci->host->id, "Current iso context not set"); + PRINT(KERN_ERR, ctx->ohci->host->id, + "Current iso context not set"); } else res = dma_region_mmap(&ctx->current_ctx->dma, file, vma); unlock_kernel(); @@ -1189,6 +1190,40 @@ static int video1394_mmap(struct file *file, struct vm_area_struct *vma) return res; } +static unsigned int video1394_poll(struct file *file, poll_table *pt) +{ + struct file_ctx *ctx; + unsigned int mask = 0; + unsigned long flags; + struct dma_iso_ctx *d; + int i; + + lock_kernel(); + ctx = file->private_data; + d = ctx->current_ctx; + if (d == NULL) { + PRINT(KERN_ERR, ctx->ohci->host->id, + "Current iso context not set"); + mask = POLLERR; + goto done; + } + + poll_wait(file, &d->waitq, pt); + + spin_lock_irqsave(&d->lock, flags); + for (i = 0; i < d->num_desc; i++) { + if (d->buffer_status[i] == VIDEO1394_BUFFER_READY) { + mask |= POLLIN | POLLRDNORM; + break; + } + } + spin_unlock_irqrestore(&d->lock, flags); +done: + unlock_kernel(); + + return mask; +} + static int video1394_open(struct inode *inode, struct file *file) { int i = ieee1394_file_to_instance(file); @@ -1257,6 +1292,7 @@ static struct file_operations video1394_fops= #ifdef CONFIG_COMPAT .compat_ioctl = video1394_compat_ioctl, #endif + .poll = video1394_poll, .mmap = video1394_mmap, .open = video1394_open, .release = video1394_release -- cgit v1.2.3 From 611aa19fd60fe57059d9972fa6ae29f7472a13cf Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 2 Aug 2006 18:44:00 +0200 Subject: ieee1394: safer definition of empty macros A deactivated macro, defined as "#define foo(bar)", will result in silent corruption if somebody forgets a semicolon after a call to foo. Replace it by "#define foo(bar) do {} while (0)" which will reveal any respective syntax errors. Signed-off-by: Stefan Richter --- drivers/ieee1394/dv1394.c | 4 ++-- drivers/ieee1394/ieee1394_core.c | 2 +- drivers/ieee1394/ieee1394_types.h | 2 +- drivers/ieee1394/ohci1394.c | 8 ++++---- drivers/ieee1394/raw1394.c | 2 +- drivers/ieee1394/sbp2.c | 18 +++++++++--------- drivers/ieee1394/video1394.c | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 6e71d68b109..6c72f04b2b5 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -137,13 +137,13 @@ #if DV1394_DEBUG_LEVEL >= 2 #define irq_printk( args... ) printk( args ) #else -#define irq_printk( args... ) +#define irq_printk( args... ) do {} while (0) #endif #if DV1394_DEBUG_LEVEL >= 1 #define debug_printk( args... ) printk( args) #else -#define debug_printk( args... ) +#define debug_printk( args... ) do {} while (0) #endif /* issue a dummy PCI read to force the preceding write diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index 991c378496f..5fccf9f7a1d 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -85,7 +85,7 @@ static void dump_packet(const char *text, quadlet_t *data, int size, int speed) printk("\n"); } #else -#define dump_packet(a,b,c,d) +#define dump_packet(a,b,c,d) do {} while (0) #endif static void abort_requests(struct hpsb_host *host); diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h index a8de375e79b..9803aaa15be 100644 --- a/drivers/ieee1394/ieee1394_types.h +++ b/drivers/ieee1394/ieee1394_types.h @@ -41,7 +41,7 @@ typedef u16 arm_length_t; #define HPSB_VERBOSE(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args) #define HPSB_DEBUG_TLABELS #else -#define HPSB_VERBOSE(fmt, args...) +#define HPSB_VERBOSE(fmt, args...) do {} while (0) #endif #ifdef __BIG_ENDIAN diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 330dcf7c699..ea14c831ff4 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -136,7 +136,7 @@ #define DBGMSG(fmt, args...) \ printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args) #else -#define DBGMSG(fmt, args...) +#define DBGMSG(fmt, args...) do {} while (0) #endif #ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG @@ -148,8 +148,8 @@ printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host-> --global_outstanding_dmas, ## args) static int global_outstanding_dmas = 0; #else -#define OHCI_DMA_ALLOC(fmt, args...) -#define OHCI_DMA_FREE(fmt, args...) +#define OHCI_DMA_ALLOC(fmt, args...) do {} while (0) +#define OHCI_DMA_FREE(fmt, args...) do {} while (0) #endif /* print general (card independent) information */ @@ -210,7 +210,7 @@ static inline void packet_swab(quadlet_t *data, int tcode) } #else /* Don't waste cycles on same sex byte swaps */ -#define packet_swab(w,x) +#define packet_swab(w,x) do {} while (0) #endif /* !LITTLE_ENDIAN */ /*********************************** diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 840b705fd5d..47e66759324 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -67,7 +67,7 @@ #define DBGMSG(fmt, args...) \ printk(KERN_INFO "raw1394:" fmt "\n" , ## args) #else -#define DBGMSG(fmt, args...) +#define DBGMSG(fmt, args...) do {} while (0) #endif static LIST_HEAD(host_info_list); diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 1c8ce7acba8..668b4512def 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -203,9 +203,9 @@ static u32 global_outstanding_command_orbs = 0; #define outstanding_orb_incr global_outstanding_command_orbs++ #define outstanding_orb_decr global_outstanding_command_orbs-- #else -#define SBP2_ORB_DEBUG(fmt, args...) -#define outstanding_orb_incr -#define outstanding_orb_decr +#define SBP2_ORB_DEBUG(fmt, args...) do {} while (0) +#define outstanding_orb_incr do {} while (0) +#define outstanding_orb_decr do {} while (0) #endif #ifdef CONFIG_IEEE1394_SBP2_DEBUG_DMA @@ -217,8 +217,8 @@ static u32 global_outstanding_command_orbs = 0; --global_outstanding_dmas, ## args) static u32 global_outstanding_dmas = 0; #else -#define SBP2_DMA_ALLOC(fmt, args...) -#define SBP2_DMA_FREE(fmt, args...) +#define SBP2_DMA_ALLOC(fmt, args...) do {} while (0) +#define SBP2_DMA_FREE(fmt, args...) do {} while (0) #endif #if CONFIG_IEEE1394_SBP2_DEBUG >= 2 @@ -232,7 +232,7 @@ static u32 global_outstanding_dmas = 0; #define SBP2_NOTICE(fmt, args...) HPSB_NOTICE("sbp2: "fmt, ## args) #define SBP2_WARN(fmt, args...) HPSB_WARN("sbp2: "fmt, ## args) #else -#define SBP2_DEBUG(fmt, args...) +#define SBP2_DEBUG(fmt, args...) do {} while (0) #define SBP2_INFO(fmt, args...) HPSB_INFO("sbp2: "fmt, ## args) #define SBP2_NOTICE(fmt, args...) HPSB_NOTICE("sbp2: "fmt, ## args) #define SBP2_WARN(fmt, args...) HPSB_WARN("sbp2: "fmt, ## args) @@ -375,8 +375,8 @@ static inline void sbp2util_cpu_to_be32_buffer(void *buffer, int length) } #else /* BIG_ENDIAN */ /* Why waste the cpu cycles? */ -#define sbp2util_be32_to_cpu_buffer(x,y) -#define sbp2util_cpu_to_be32_buffer(x,y) +#define sbp2util_be32_to_cpu_buffer(x,y) do {} while (0) +#define sbp2util_cpu_to_be32_buffer(x,y) do {} while (0) #endif #ifdef CONFIG_IEEE1394_SBP2_PACKET_DUMP @@ -412,7 +412,7 @@ static void sbp2util_packet_dump(void *buffer, int length, char *dump_name, return; } #else -#define sbp2util_packet_dump(w,x,y,z) +#define sbp2util_packet_dump(w,x,y,z) do {} while (0) #endif static DECLARE_WAIT_QUEUE_HEAD(access_wq); diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index af78b840dc2..9bc65059cc6 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -129,7 +129,7 @@ struct file_ctx { #define DBGMSG(card, fmt, args...) \ printk(KERN_INFO "video1394_%d: " fmt "\n" , card , ## args) #else -#define DBGMSG(card, fmt, args...) +#define DBGMSG(card, fmt, args...) do {} while (0) #endif /* print general (card independent) information */ -- cgit v1.2.3 From 2a874182842c6a70f245b7f1ad859f9152517951 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 11 Aug 2006 16:46:14 -0700 Subject: CONFIG_PM=n slim: drivers/ieee1394/ohci1394.c Remove some code which is unneeded if CONFIG_PM=n. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Stefan Richter --- drivers/ieee1394/ohci1394.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index ea14c831ff4..9890ab73bb5 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -3530,7 +3530,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) put_device(dev); } - +#ifdef CONFIG_PM static int ohci1394_pci_resume (struct pci_dev *pdev) { #ifdef CONFIG_PPC_PMAC @@ -3568,7 +3568,7 @@ static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) return 0; } - +#endif #define PCI_CLASS_FIREWIRE_OHCI ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10) @@ -3591,8 +3591,10 @@ static struct pci_driver ohci1394_pci_driver = { .id_table = ohci1394_pci_tbl, .probe = ohci1394_pci_probe, .remove = ohci1394_pci_remove, +#ifdef CONFIG_PM .resume = ohci1394_pci_resume, .suspend = ohci1394_pci_suspend, +#endif }; /*********************************** -- cgit v1.2.3 From 09ee67abe997ee95cd3f6cc552fa9532bc722d83 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 14 Aug 2006 18:43:00 +0200 Subject: ieee1394: sbp2: handle "sbp2util_node_write_no_wait failed" Fix for http://bugzilla.kernel.org/show_bug.cgi?id=6948 Because sbp2 writes to the target's fetch agent's registers from within atomic context, it cannot sleep to guaranteedly get a free transaction label. This may repeatedly lead to "sbp2util_node_write_no_wait failed" and consequently to SCSI command abortion after timeout. A likely cause is that many queue_command softirqs may occur before khpsbpkt (the ieee1394 driver's thread which cleans up after finished transactions) is woken up to recycle tlabels. Sbp2 now schedules a workqueue job whenever sbp2_link_orb_command fails in sbp2util_node_write_no_wait. The job will reliably get a transaction label because it can sleep. We use the kernel-wide shared workqueue because it is unlikely that the job itself actually needs to sleep. In the improbable case that it has to sleep, it doesn't need to sleep long since the standard transaction timeout is 100ms. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 71 +++++++++++++++++++++++++++++++++++++++++++++---- drivers/ieee1394/sbp2.h | 3 +++ 2 files changed, 69 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 668b4512def..c4d30a7b8b1 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -465,6 +465,44 @@ static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr, return 0; } +static void sbp2util_notify_fetch_agent(struct scsi_id_instance_data *scsi_id, + u64 offset, quadlet_t *data, size_t len) +{ + /* + * There is a small window after a bus reset within which the node + * entry's generation is current but the reconnect wasn't completed. + */ + if (atomic_read(&scsi_id->unfinished_reset)) + return; + + if (hpsb_node_write(scsi_id->ne, + scsi_id->sbp2_command_block_agent_addr + offset, + data, len)) + SBP2_ERR("sbp2util_notify_fetch_agent failed."); + /* + * Now accept new SCSI commands, unless a bus reset happended during + * hpsb_node_write. + */ + if (!atomic_read(&scsi_id->unfinished_reset)) + scsi_unblock_requests(scsi_id->scsi_host); +} + +static void sbp2util_write_orb_pointer(void *p) +{ + quadlet_t data[2]; + + data[0] = ORB_SET_NODE_ID( + ((struct scsi_id_instance_data *)p)->hi->host->node_id); + data[1] = ((struct scsi_id_instance_data *)p)->last_orb_dma; + sbp2util_cpu_to_be32_buffer(data, 8); + sbp2util_notify_fetch_agent(p, SBP2_ORB_POINTER_OFFSET, data, 8); +} + +static void sbp2util_write_doorbell(void *p) +{ + sbp2util_notify_fetch_agent(p, SBP2_DOORBELL_OFFSET, NULL, 4); +} + /* * This function is called to create a pool of command orbs used for * command processing. It is called when a new sbp2 device is detected. @@ -712,6 +750,7 @@ static int sbp2_remove(struct device *dev) sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT); /* scsi_remove_device() will trigger shutdown functions of SCSI * highlevel drivers which would deadlock if blocked. */ + atomic_set(&scsi_id->unfinished_reset, 0); scsi_unblock_requests(scsi_id->scsi_host); } sdev = scsi_id->sdev; @@ -765,6 +804,7 @@ static int sbp2_update(struct unit_directory *ud) /* Make sure we unblock requests (since this is likely after a bus * reset). */ + atomic_set(&scsi_id->unfinished_reset, 0); scsi_unblock_requests(scsi_id->scsi_host); return 0; @@ -795,6 +835,8 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); INIT_LIST_HEAD(&scsi_id->scsi_list); spin_lock_init(&scsi_id->sbp2_command_orb_lock); + atomic_set(&scsi_id->unfinished_reset, 0); + INIT_WORK(&scsi_id->protocol_work, NULL, NULL); ud->device.driver_data = scsi_id; @@ -879,8 +921,10 @@ static void sbp2_host_reset(struct hpsb_host *host) hi = hpsb_get_hostinfo(&sbp2_highlevel, host); if (hi) { - list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list) + list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list) { + atomic_set(&scsi_id->unfinished_reset, 1); scsi_block_requests(scsi_id->scsi_host); + } } } @@ -1032,7 +1076,7 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) scsi_remove_host(scsi_id->scsi_host); scsi_host_put(scsi_id->scsi_host); } - + flush_scheduled_work(); sbp2util_remove_command_orb_pool(scsi_id); list_del(&scsi_id->scsi_list); @@ -1661,6 +1705,10 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait) SBP2_DEBUG_ENTER(); + cancel_delayed_work(&scsi_id->protocol_work); + if (wait) + flush_scheduled_work(); + data = ntohl(SBP2_AGENT_RESET_DATA); addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET; @@ -1982,9 +2030,22 @@ static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, SBP2_ORB_DEBUG("write to %s register, command orb %p", last_orb ? "DOORBELL" : "ORB_POINTER", command_orb); - if (sbp2util_node_write_no_wait(scsi_id->ne, addr, data, length)) - SBP2_ERR("sbp2util_node_write_no_wait failed.\n"); - /* We rely on SCSI EH to deal with _node_write_ failures. */ + if (sbp2util_node_write_no_wait(scsi_id->ne, addr, data, length)) { + /* + * sbp2util_node_write_no_wait failed. We certainly ran out + * of transaction labels, perhaps just because there were no + * context switches which gave khpsbpkt a chance to collect + * free tlabels. Try again in non-atomic context. If necessary, + * the workqueue job will sleep to guaranteedly get a tlabel. + * We do not accept new commands until the job is over. + */ + scsi_block_requests(scsi_id->scsi_host); + PREPARE_WORK(&scsi_id->protocol_work, + last_orb ? sbp2util_write_doorbell: + sbp2util_write_orb_pointer, + scsi_id); + schedule_work(&scsi_id->protocol_work); + } } /* diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index 89098fe565e..1c9fe422cf4 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -346,6 +346,9 @@ struct scsi_id_instance_data { /* Device specific workarounds/brokeness */ unsigned workarounds; + + atomic_t unfinished_reset; + struct work_struct protocol_work; }; /* Sbp2 host data structure (one per IEEE1394 host) */ -- cgit v1.2.3 From 1f427e8055b1ab408395d6da421d93783120484c Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 14 Aug 2006 18:44:00 +0200 Subject: ieee1394: sbp2: safer agent reset in error handlers The scsi_host_template's eh_abort_handler and eh_device_reset_handler are allowed to sleep. Use this to run sbp2_agent_reset in the more reliable mode which returns _after_ its write transaction was finished. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index c4d30a7b8b1..b5bcca36d43 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -2578,7 +2578,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) /* * Initiate a fetch agent reset. */ - sbp2_agent_reset(scsi_id, 0); + sbp2_agent_reset(scsi_id, 1); sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); } @@ -2597,7 +2597,7 @@ static int sbp2scsi_reset(struct scsi_cmnd *SCpnt) if (sbp2util_node_is_available(scsi_id)) { SBP2_ERR("Generating sbp2 fetch agent reset"); - sbp2_agent_reset(scsi_id, 0); + sbp2_agent_reset(scsi_id, 1); } return SUCCESS; -- cgit v1.2.3 From 4fc383c09d14783ca7d7e97e2134abbe7dc43230 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 14 Aug 2006 18:46:00 +0200 Subject: ieee1394: sbp2: recheck node generation in sbp2_update While sbp2_update() is doing its duties after a bus reset, another reset could happen. Don't accept new requests until the next undisturbed sbp2_update() or until sbp2_remove(). Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index b5bcca36d43..5440cd05026 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -802,11 +802,12 @@ static int sbp2_update(struct unit_directory *ud) */ sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); - /* Make sure we unblock requests (since this is likely after a bus - * reset). */ - atomic_set(&scsi_id->unfinished_reset, 0); - scsi_unblock_requests(scsi_id->scsi_host); - + /* Accept new commands unless there was another bus reset in the + * meantime. */ + if (hpsb_node_entry_valid(scsi_id->ne)) { + atomic_set(&scsi_id->unfinished_reset, 0); + scsi_unblock_requests(scsi_id->scsi_host); + } return 0; } -- cgit v1.2.3 From abbca103a02ff0e87569c38be518f9cb2d6baabc Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 14 Aug 2006 18:51:00 +0200 Subject: ieee1394: sbp2: better handling of transport errors If the target signals a transport failure via status block, complete the request with DID_BUSY to indicate to the SCSI subsystem that the command may succeed when retried. Also log diagnostic information if the status block shows a transport related problem. It may point to hardware faults. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 16 +++++++++++----- drivers/ieee1394/sbp2.h | 6 +++--- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 5440cd05026..6b3350f71a8 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -2213,28 +2213,34 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); if (SCpnt) { - if (STATUS_TEST_RS(sb->ORB_offset_hi_misc)) + u32 h = sb->ORB_offset_hi_misc; + u32 r = STATUS_GET_RESP(h); + + if (r != RESP_STATUS_REQUEST_COMPLETE) { + SBP2_WARN("resp 0x%x, sbp_status 0x%x", + r, STATUS_GET_SBP_STATUS(h)); scsi_status = + r == RESP_STATUS_TRANSPORT_FAILURE ? + SBP2_SCSI_STATUS_BUSY : SBP2_SCSI_STATUS_COMMAND_TERMINATED; + } /* * See if the target stored any scsi status information. */ - if (STATUS_GET_LEN(sb->ORB_offset_hi_misc) > 1) { + if (STATUS_GET_LEN(h) > 1) { SBP2_DEBUG("CHECK CONDITION"); scsi_status = sbp2_status_to_sense_data( (unchar *)sb, SCpnt->sense_buffer); } - /* * Check to see if the dead bit is set. If so, we'll * have to initiate a fetch agent reset. */ - if (STATUS_TEST_D(sb->ORB_offset_hi_misc)) { + if (STATUS_TEST_DEAD(h)) { SBP2_DEBUG("Dead bit set - " "initiating fetch agent reset"); sbp2_agent_reset(scsi_id, 0); } - SBP2_ORB_DEBUG("completing command orb %p", &command->command_orb); } diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index 1c9fe422cf4..34c52bf4fa3 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -181,11 +181,11 @@ struct sbp2_unrestricted_page_table { #define SBP2_SCSI_STATUS_SELECTION_TIMEOUT 0xff #define STATUS_GET_SRC(value) (((value) >> 30) & 0x3) +#define STATUS_GET_RESP(value) (((value) >> 28) & 0x3) #define STATUS_GET_LEN(value) (((value) >> 24) & 0x7) +#define STATUS_GET_SBP_STATUS(value) (((value) >> 16) & 0xff) #define STATUS_GET_ORB_OFFSET_HI(value) ((value) & 0x0000ffff) -#define STATUS_TEST_D(value) ((value) & 0x08000000) -/* test 'resp' | 'sbp2_status' */ -#define STATUS_TEST_RS(value) ((value) & 0x30ff0000) +#define STATUS_TEST_DEAD(value) ((value) & 0x08000000) /* test 'resp' | 'dead' | 'sbp2_status' */ #define STATUS_TEST_RDS(value) ((value) & 0x38ff0000) -- cgit v1.2.3 From 902abed1587805fe8513e10aef6643f58a6de0a6 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 14 Aug 2006 18:56:00 +0200 Subject: ieee1394: sbp2: update includes Remove unused includes. Add missing includes, i.e. explicitly include all used headers. Sort includes alphabetically. Replace one call to signal_pending(current) to avoid to include headers just for this line. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 6b3350f71a8..3cb6b479b2e 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -38,31 +38,36 @@ * but the code needs additional debugging. */ +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include #include -#include +#include +#include #include +#include +#include + +#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA +#include /* for bus_to_virt */ +#endif #include #include @@ -71,13 +76,14 @@ #include #include "csr1212.h" +#include "highlevel.h" +#include "hosts.h" #include "ieee1394.h" -#include "ieee1394_types.h" #include "ieee1394_core.h" -#include "nodemgr.h" -#include "hosts.h" -#include "highlevel.h" +#include "ieee1394_hotplug.h" #include "ieee1394_transactions.h" +#include "ieee1394_types.h" +#include "nodemgr.h" #include "sbp2.h" /* @@ -1011,8 +1017,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id) * connected to the sbp2 device being removed. That host would * have a certain amount of time to relogin before the sbp2 device * allows someone else to login instead. One second makes sense. */ - msleep_interruptible(1000); - if (signal_pending(current)) { + if (msleep_interruptible(1000)) { sbp2_remove_device(scsi_id); return -EINTR; } -- cgit v1.2.3 From 2cccbb555c77e641de9008660e08bdf17fc4206a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 14 Aug 2006 18:59:00 +0200 Subject: ieee1394: sbp2: prevent rare deadlock in shutdown Scsi_remove_device() may go into uninterruptible sleep if blocked. Therefore sbp2_remove() unblocks the Scsi_Host before the device is requested to be removed. But there could be another 1394 bus reset after that which would block the host again. The 1394 subsystem won't call sbp2_update() concurrently to sbp2_remove(), which is why there is no chance for sbp2_remove() to be unblocked by sbp2_update(). The fix is to tell sbp2's bus reset handler when a device is to be shut down so that it skips scsi_block_requests() on that host. As before, any new commands after a reset without reconnect will be failed quickly by sbp2scsi_queuecommand(). In the long term, means to go without scsi_block_requests() should be found. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 21 +++++++++++---------- drivers/ieee1394/sbp2.h | 9 ++++++++- 2 files changed, 19 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 3cb6b479b2e..017259cc34f 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -478,7 +478,7 @@ static void sbp2util_notify_fetch_agent(struct scsi_id_instance_data *scsi_id, * There is a small window after a bus reset within which the node * entry's generation is current but the reconnect wasn't completed. */ - if (atomic_read(&scsi_id->unfinished_reset)) + if (unlikely(atomic_read(&scsi_id->state) == SBP2LU_STATE_IN_RESET)) return; if (hpsb_node_write(scsi_id->ne, @@ -489,7 +489,7 @@ static void sbp2util_notify_fetch_agent(struct scsi_id_instance_data *scsi_id, * Now accept new SCSI commands, unless a bus reset happended during * hpsb_node_write. */ - if (!atomic_read(&scsi_id->unfinished_reset)) + if (likely(atomic_read(&scsi_id->state) != SBP2LU_STATE_IN_RESET)) scsi_unblock_requests(scsi_id->scsi_host); } @@ -756,7 +756,7 @@ static int sbp2_remove(struct device *dev) sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT); /* scsi_remove_device() will trigger shutdown functions of SCSI * highlevel drivers which would deadlock if blocked. */ - atomic_set(&scsi_id->unfinished_reset, 0); + atomic_set(&scsi_id->state, SBP2LU_STATE_IN_SHUTDOWN); scsi_unblock_requests(scsi_id->scsi_host); } sdev = scsi_id->sdev; @@ -811,7 +811,7 @@ static int sbp2_update(struct unit_directory *ud) /* Accept new commands unless there was another bus reset in the * meantime. */ if (hpsb_node_entry_valid(scsi_id->ne)) { - atomic_set(&scsi_id->unfinished_reset, 0); + atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING); scsi_unblock_requests(scsi_id->scsi_host); } return 0; @@ -842,7 +842,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); INIT_LIST_HEAD(&scsi_id->scsi_list); spin_lock_init(&scsi_id->sbp2_command_orb_lock); - atomic_set(&scsi_id->unfinished_reset, 0); + atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING); INIT_WORK(&scsi_id->protocol_work, NULL, NULL); ud->device.driver_data = scsi_id; @@ -926,13 +926,14 @@ static void sbp2_host_reset(struct hpsb_host *host) struct scsi_id_instance_data *scsi_id; hi = hpsb_get_hostinfo(&sbp2_highlevel, host); - - if (hi) { - list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list) { - atomic_set(&scsi_id->unfinished_reset, 1); + if (!hi) + return; + list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list) + if (likely(atomic_read(&scsi_id->state) != + SBP2LU_STATE_IN_SHUTDOWN)) { + atomic_set(&scsi_id->state, SBP2LU_STATE_IN_RESET); scsi_block_requests(scsi_id->scsi_host); } - } } /* diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index 34c52bf4fa3..abbe48e646c 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -347,10 +347,17 @@ struct scsi_id_instance_data { /* Device specific workarounds/brokeness */ unsigned workarounds; - atomic_t unfinished_reset; + atomic_t state; struct work_struct protocol_work; }; +/* For use in scsi_id_instance_data.state */ +enum sbp2lu_state_types { + SBP2LU_STATE_RUNNING, /* all normal */ + SBP2LU_STATE_IN_RESET, /* between bus reset and reconnect */ + SBP2LU_STATE_IN_SHUTDOWN /* when sbp2_remove was called */ +}; + /* Sbp2 host data structure (one per IEEE1394 host) */ struct sbp2scsi_host_info { struct hpsb_host *host; /* IEEE1394 host */ -- cgit v1.2.3 From b809289df06ff9453c1b19df74ea83aba311dfc6 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 30 Aug 2006 18:22:00 +0200 Subject: ieee1394: sbp2: more help in Kconfig Add some pointers to SCSI to the configuration menu item of sbp2. Signed-off-by: Stefan Richter --- drivers/ieee1394/Kconfig | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig index 186737539cf..2769e505f05 100644 --- a/drivers/ieee1394/Kconfig +++ b/drivers/ieee1394/Kconfig @@ -120,12 +120,19 @@ config IEEE1394_VIDEO1394 this option only if you have an IEEE 1394 video device connected to an OHCI-1394 card. +comment "SBP-2 support (for storage devices) requires SCSI" + depends on IEEE1394 && SCSI=n + config IEEE1394_SBP2 tristate "SBP-2 support (Harddisks etc.)" depends on IEEE1394 && SCSI && (PCI || BROKEN) help - This option enables you to use SBP-2 devices connected to your IEEE - 1394 bus. SBP-2 devices include harddrives and DVD devices. + This option enables you to use SBP-2 devices connected to an IEEE + 1394 bus. SBP-2 devices include storage devices like harddisks and + DVD drives, also some other FireWire devices like scanners. + + You should also enable support for disks, CD-ROMs, etc. in the SCSI + configuration section. config IEEE1394_SBP2_PHYS_DMA bool "Enable replacement for physical DMA in SBP2" -- cgit v1.2.3 From 9b516010863195ba7db061233a3eeffe779130e8 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 6 Sep 2006 19:04:00 +0200 Subject: ieee1394: nodemgr: fix rwsem recursion nodemgr_update_pdrv grabbed an rw semaphore (as reader) which was already taken by its caller's caller, nodemgr_probe_ne (as reader too). Reported by Miles Lane, call path pointed out by Arjan van de Ven. FIXME: Shouldn't we rather use class->sem there, not class->subsys.rwsem? Signed-off-by: Stefan Richter --- drivers/ieee1394/nodemgr.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index eabc51b23c0..f087f7e2b69 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -1316,6 +1316,7 @@ static void nodemgr_node_scan(struct host_info *hi, int generation) } +/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */ static void nodemgr_suspend_ne(struct node_entry *ne) { struct class_device *cdev; @@ -1368,15 +1369,14 @@ static void nodemgr_resume_ne(struct node_entry *ne) } +/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */ static void nodemgr_update_pdrv(struct node_entry *ne) { struct unit_directory *ud; struct hpsb_protocol_driver *pdrv; - struct class *class = &nodemgr_ud_class; struct class_device *cdev; - down_read(&class->subsys.rwsem); - list_for_each_entry(cdev, &class->children, node) { + list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { ud = container_of(cdev, struct unit_directory, class_dev); if (ud->ne != ne || !ud->device.driver) continue; @@ -1389,7 +1389,6 @@ static void nodemgr_update_pdrv(struct node_entry *ne) up_write(&ud->device.bus->subsys.rwsem); } } - up_read(&class->subsys.rwsem); } @@ -1420,6 +1419,8 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation) } +/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader because the + * calls to nodemgr_update_pdrv() and nodemgr_suspend_ne() here require it. */ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation) { struct device *dev; -- cgit v1.2.3 From a1842be898a2295ef513ed0a5d26f65d6283cb11 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 6 Sep 2006 19:04:00 +0200 Subject: ieee1394: nodemgr: grab class.subsys.rwsem in nodemgr_resume_ne nodemgr_resume_ne was iterating over nodemgr_ud_class.children without protection by nodemgr_ud_class.subsys.rwsem. FIXME: Shouldn't we rather use class->sem there, not class->subsys.rwsem? Signed-off-by: Stefan Richter --- drivers/ieee1394/nodemgr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index f087f7e2b69..3e7974c5744 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -1352,6 +1352,7 @@ static void nodemgr_resume_ne(struct node_entry *ne) ne->in_limbo = 0; device_remove_file(&ne->device, &dev_attr_ne_in_limbo); + down_read(&nodemgr_ud_class.subsys.rwsem); down_read(&ne->device.bus->subsys.rwsem); list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { ud = container_of(cdev, struct unit_directory, class_dev); @@ -1363,6 +1364,7 @@ static void nodemgr_resume_ne(struct node_entry *ne) ud->device.driver->resume(&ud->device); } up_read(&ne->device.bus->subsys.rwsem); + up_read(&nodemgr_ud_class.subsys.rwsem); HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); -- cgit v1.2.3 From 98e238cd42be6c0852da519303cf0182690f8d9f Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 7 Sep 2006 01:06:00 +0200 Subject: ieee1394: sbp2: don't prefer MODE SENSE 10 In the old days, sbp2 used to coerce all MODE SENSE commands into the 10 bytes version. When all command set conversions were removed from sbp2 several months ago, sdev->use_10_for_ms = 1 was added. Meaning, higher SCSI layers preferred the 10 bytes version but would try the 6 bytes version if the former failed. Recently, a problem with the 10 bytes version was discovered. An Initio INIC-1530 firmware accepted the 10 bytes version but replied with bogus data, showing the HDD incorrectly as write-protected. Since RBC actually mandates MODE SENSE (6), I checked which version was sent by Windows XP and Mac OS X 10.3 to an SBP-2 target hosted by Linux --- it was the 6 bytes version. (Exception: OS X sent the 10 bytes version to an MMC target. RBC and SBC got MODE SENSE (6).) Therefore, drop the use_10_for_ms flag from sbp2. Now the upper layers will try MODE SENSE (6) before MODE SENSE (10) on all SBP-2 devices. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 017259cc34f..f192596329e 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -2528,7 +2528,6 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev) blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); sdev->use_10_for_rw = 1; - sdev->use_10_for_ms = 1; if (sdev->type == TYPE_DISK && scsi_id->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) -- cgit v1.2.3 From cf82703dc6f8197341ca6be33cd38e80332685f0 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 7 Sep 2006 15:52:00 +0200 Subject: ieee1394: ohci1394: fix endianess bug in debug message The transaction labels were misprinted int the debug printk "Packet received from node..." due two byte-swapping once too often. Affected were big endian machines, except UniNorth based ones. Fix tested by Wolfgang Pfeiffer. Signed-off-by: Stefan Richter --- drivers/ieee1394/ohci1394.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 9890ab73bb5..4622c99c12f 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -2739,7 +2739,7 @@ static void dma_rcv_tasklet (unsigned long data) (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f, (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>21)&0x3, tcode, length, d->ctx, - (cond_le32_to_cpu(d->spb[0], ohci->no_swap_incoming)>>10)&0x3f); + (d->spb[0]>>10)&0x3f); ack = (((cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f) == 0x11) ? 1 : 0; -- cgit v1.2.3 From 9531f13ae56b136d0ad09e6e5c8308a7dc58f3f0 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 7 Sep 2006 20:36:00 +0200 Subject: ieee1394: ohci1394: more obvious endianess handling Rename ohci1394's packet_swab to header_le32_to_cpu to better reflect what it actually does. Also, define a constant array as 'const' and check the array index properly. Signed-off-by: Stefan Richter --- drivers/ieee1394/ohci1394.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 4622c99c12f..8d92246bdc3 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -181,36 +181,35 @@ static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, static void ohci1394_pci_remove(struct pci_dev *pdev); #ifndef __LITTLE_ENDIAN -static unsigned hdr_sizes[] = -{ +const static size_t hdr_sizes[] = { 3, /* TCODE_WRITEQ */ 4, /* TCODE_WRITEB */ 3, /* TCODE_WRITE_RESPONSE */ - 0, /* ??? */ + 0, /* reserved */ 3, /* TCODE_READQ */ 4, /* TCODE_READB */ 3, /* TCODE_READQ_RESPONSE */ 4, /* TCODE_READB_RESPONSE */ - 1, /* TCODE_CYCLE_START (???) */ + 1, /* TCODE_CYCLE_START */ 4, /* TCODE_LOCK_REQUEST */ 2, /* TCODE_ISO_DATA */ 4, /* TCODE_LOCK_RESPONSE */ + /* rest is reserved or link-internal */ }; -/* Swap headers */ -static inline void packet_swab(quadlet_t *data, int tcode) +static inline void header_le32_to_cpu(quadlet_t *data, unsigned char tcode) { - size_t size = hdr_sizes[tcode]; + size_t size; - if (tcode > TCODE_LOCK_RESPONSE || hdr_sizes[tcode] == 0) + if (unlikely(tcode >= ARRAY_SIZE(hdr_sizes))) return; + size = hdr_sizes[tcode]; while (size--) - data[size] = swab32(data[size]); + data[size] = le32_to_cpu(data[size]); } #else -/* Don't waste cycles on same sex byte swaps */ -#define packet_swab(w,x) do {} while (0) +#define header_le32_to_cpu(w,x) do {} while (0) #endif /* !LITTLE_ENDIAN */ /*********************************** @@ -701,7 +700,7 @@ static void insert_packet(struct ti_ohci *ohci, d->prg_cpu[idx]->data[2] = packet->header[2]; d->prg_cpu[idx]->data[3] = packet->header[3]; } - packet_swab(d->prg_cpu[idx]->data, packet->tcode); + header_le32_to_cpu(d->prg_cpu[idx]->data, packet->tcode); } if (packet->data_size) { /* block transmit */ @@ -777,7 +776,7 @@ static void insert_packet(struct ti_ohci *ohci, d->prg_cpu[idx]->data[0] = packet->speed_code<<16 | (packet->header[0] & 0xFFFF); d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000; - packet_swab(d->prg_cpu[idx]->data, packet->tcode); + header_le32_to_cpu(d->prg_cpu[idx]->data, packet->tcode); d->prg_cpu[idx]->begin.control = cpu_to_le32(DMA_CTL_OUTPUT_MORE | @@ -2731,7 +2730,7 @@ static void dma_rcv_tasklet (unsigned long data) * bus reset. We always ignore it. */ if (tcode != OHCI1394_TCODE_PHY) { if (!ohci->no_swap_incoming) - packet_swab(d->spb, tcode); + header_le32_to_cpu(d->spb, tcode); DBGMSG("Packet received from node" " %d ack=0x%02X spd=%d tcode=0x%X" " length=%d ctx=%d tlabel=%d", -- cgit v1.2.3 From f0645e7720e0baacbde61d7d1f0180309451c695 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 17 Sep 2006 19:39:06 +0200 Subject: set power state of firewire host during suspend Put firewire host controller in PCI Dx state for system suspend. (I was not able to measure any power savings, but it sounds like right thing to do, anyway.) Signed-off-by: Pavel Machek Update by stefanr: Shuffle with existing PPC_PMAC code. Set power state in the resume hook too. Signed-off-by: Stefan Richter --- drivers/ieee1394/ohci1394.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 8d92246bdc3..54d686aed39 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -3532,6 +3532,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) #ifdef CONFIG_PM static int ohci1394_pci_resume (struct pci_dev *pdev) { +/* PowerMac resume code comes first */ #ifdef CONFIG_PPC_PMAC if (machine_is(powermac)) { struct device_node *of_node; @@ -3543,17 +3544,19 @@ static int ohci1394_pci_resume (struct pci_dev *pdev) } #endif /* CONFIG_PPC_PMAC */ + pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); pci_enable_device(pdev); return 0; } - static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) { pci_save_state(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); +/* PowerMac suspend code comes last */ #ifdef CONFIG_PPC_PMAC if (machine_is(powermac)) { struct device_node *of_node; @@ -3563,11 +3566,10 @@ static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) if (of_node) pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0); } -#endif - +#endif /* CONFIG_PPC_PMAC */ return 0; } -#endif +#endif /* CONFIG_PM */ #define PCI_CLASS_FIREWIRE_OHCI ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10) -- cgit v1.2.3 From ea6104c22468239083857fa07425c312b1ecb424 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 17 Sep 2006 19:41:45 +0200 Subject: ieee1394: ohci1394: check for errors in suspend or resume Some of the suspend and resume litany may fail. Tell the PCI core about it. Signed-off-by: Stefan Richter --- drivers/ieee1394/ohci1394.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 54d686aed39..8fd0030475b 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -3546,15 +3546,19 @@ static int ohci1394_pci_resume (struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - pci_enable_device(pdev); - - return 0; + return pci_enable_device(pdev); } static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) { - pci_save_state(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); + int err; + + err = pci_save_state(pdev); + if (err) + goto out; + err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); + if (err) + goto out; /* PowerMac suspend code comes last */ #ifdef CONFIG_PPC_PMAC @@ -3567,7 +3571,8 @@ static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0); } #endif /* CONFIG_PPC_PMAC */ - return 0; +out: + return err; } #endif /* CONFIG_PM */ -- cgit v1.2.3 From c394f1eafef61c6666f5876afde6110a276c4c9f Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 7 Aug 2006 20:48:00 +0200 Subject: ieee1394: sbp2: enable auto spin-up for all SBP-2 devices This is a follow-up to patch "ieee1394: sbp2: enable auto spin-up for Maxtor disks". When I 'ejected' an OXUF922 based HDD from a Mac OS X box, it was spun down by the Mac and did not spin up by itself when attached to a Linux box right after that. The first SCSI command that required the bridge to access the drive ended in sda:<6>sd 18:0:0:0: Device not ready: <6>: Current: sense key: Not Ready Additional sense: Logical unit not ready, initializing cmd. required Therefore the flag which instructs scsi_mod to send START STOP UNIT with START=1 ("make medium ready") after such a condition is now enabled unconditionally for all FireWire storage devices. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index f192596329e..6986ac18828 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -2515,6 +2515,7 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev) (struct scsi_id_instance_data *)sdev->host->hostdata[0]; scsi_id->sdev = sdev; + sdev->allow_restart = 1; if (scsi_id->workarounds & SBP2_WORKAROUND_INQUIRY_36) sdev->inquiry_len = 36; @@ -2534,9 +2535,6 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev) sdev->skip_ms_page_8 = 1; if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) sdev->fix_capacity = 1; - if (scsi_id->ne->guid_vendor_id == 0x0010b9 && /* Maxtor's OUI */ - (sdev->type == TYPE_DISK || sdev->type == TYPE_RBC)) - sdev->allow_restart = 1; return 0; } -- cgit v1.2.3 From 3253b669eed7194ae490acb4aadab7262bbfeb8d Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 14 Sep 2006 22:05:16 +0200 Subject: ieee1394: raw1394: arm functions slept in atomic context Sleeping functions like copy_to_user were accessed inside spinlocks in raw1394's arm_register, arm_unregister, arm_get_buf, arm_set_buf. http://bugzilla.kernel.org/show_bug.cgi?id=7120 Signed-off-by: Stefan Richter Tested-by: David Trent (cherry picked from e575953ec17c3f5c1e738847d2d16c241bb99783 commit) --- drivers/ieee1394/raw1394.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 47e66759324..5ec4f5eb6b1 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -1774,6 +1774,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req) addr->notification_options |= addr->client_transactions; addr->recvb = req->req.recvb; addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF); + spin_lock_irqsave(&host_info_lock, flags); hi = find_host_info(fi->host); same_host = 0; @@ -1799,9 +1800,9 @@ static int arm_register(struct file_info *fi, struct pending_request *req) } if (same_host) { /* addressrange occupied by same host */ + spin_unlock_irqrestore(&host_info_lock, flags); vfree(addr->addr_space_buffer); kfree(addr); - spin_unlock_irqrestore(&host_info_lock, flags); return (-EALREADY); } /* another host with valid address-entry containing same addressrange */ @@ -1829,6 +1830,8 @@ static int arm_register(struct file_info *fi, struct pending_request *req) } } } + spin_unlock_irqrestore(&host_info_lock, flags); + if (another_host) { DBGMSG("another hosts entry is valid -> SUCCESS"); if (copy_to_user(int2ptr(req->req.recvb), @@ -1837,11 +1840,11 @@ static int arm_register(struct file_info *fi, struct pending_request *req) " address-range-entry is invalid -> EFAULT !!!\n"); vfree(addr->addr_space_buffer); kfree(addr); - spin_unlock_irqrestore(&host_info_lock, flags); return (-EFAULT); } free_pending_request(req); /* immediate success or fail */ /* INSERT ENTRY */ + spin_lock_irqsave(&host_info_lock, flags); list_add_tail(&addr->addr_list, &fi->addr_list); spin_unlock_irqrestore(&host_info_lock, flags); return sizeof(struct raw1394_request); @@ -1852,15 +1855,15 @@ static int arm_register(struct file_info *fi, struct pending_request *req) req->req.address + req->req.length); if (retval) { /* INSERT ENTRY */ + spin_lock_irqsave(&host_info_lock, flags); list_add_tail(&addr->addr_list, &fi->addr_list); + spin_unlock_irqrestore(&host_info_lock, flags); } else { DBGMSG("arm_register failed errno: %d \n", retval); vfree(addr->addr_space_buffer); kfree(addr); - spin_unlock_irqrestore(&host_info_lock, flags); return (-EALREADY); } - spin_unlock_irqrestore(&host_info_lock, flags); free_pending_request(req); /* immediate success or fail */ return sizeof(struct raw1394_request); } @@ -1926,10 +1929,10 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req) if (another_host) { DBGMSG("delete entry from list -> success"); list_del(&addr->addr_list); + spin_unlock_irqrestore(&host_info_lock, flags); vfree(addr->addr_space_buffer); kfree(addr); free_pending_request(req); /* immediate success or fail */ - spin_unlock_irqrestore(&host_info_lock, flags); return sizeof(struct raw1394_request); } retval = @@ -1971,23 +1974,19 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req) (arm_addr->end > req->req.address)) { if (req->req.address + req->req.length <= arm_addr->end) { offset = req->req.address - arm_addr->start; + spin_unlock_irqrestore(&host_info_lock, flags); DBGMSG ("arm_get_buf copy_to_user( %08X, %p, %u )", (u32) req->req.recvb, arm_addr->addr_space_buffer + offset, (u32) req->req.length); - if (copy_to_user (int2ptr(req->req.recvb), arm_addr->addr_space_buffer + offset, - req->req.length)) { - spin_unlock_irqrestore(&host_info_lock, - flags); + req->req.length)) return (-EFAULT); - } - spin_unlock_irqrestore(&host_info_lock, flags); /* We have to free the request, because we * queue no response, and therefore nobody * will free it. */ @@ -2027,24 +2026,23 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req) (arm_addr->end > req->req.address)) { if (req->req.address + req->req.length <= arm_addr->end) { offset = req->req.address - arm_addr->start; + spin_unlock_irqrestore(&host_info_lock, flags); DBGMSG ("arm_set_buf copy_from_user( %p, %08X, %u )", arm_addr->addr_space_buffer + offset, (u32) req->req.sendb, (u32) req->req.length); - if (copy_from_user (arm_addr->addr_space_buffer + offset, int2ptr(req->req.sendb), - req->req.length)) { - spin_unlock_irqrestore(&host_info_lock, - flags); + req->req.length)) return (-EFAULT); - } - spin_unlock_irqrestore(&host_info_lock, flags); - free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + /* We have to free the request, because we + * queue no response, and therefore nobody + * will free it. */ + free_pending_request(req); return sizeof(struct raw1394_request); } else { DBGMSG("arm_set_buf request exceeded mapping"); -- cgit v1.2.3