Commit 71780f59 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6: (31 commits)
  firewire: fw-sbp2: fix DMA mapping of management ORBs
  firewire: fw-sbp2: fix DMA mapping of command ORBs
  firewire: fw-sbp2: fix DMA mapping of S/G tables
  firewire: fw-sbp2: add a boundary check
  firewire: fw-sbp2: correctly align page tables
  firewire: fw-sbp2: memset wants string.h
  firewire: fw-sbp2: use correct speed in sbp2_agent_reset
  firewire: fw-sbp2: correctly dereference by container_of
  firewire: Document userspace ioctl interface.
  firewire: fw-sbp2: implement nonexclusive login
  firewire: fw-sbp2: let SCSI shutdown commands through before logout
  firewire: fw-sbp2: implement max sectors limit for some old bridges
  firewire: simplify a struct type
  firewire: support S100B...S400B and link slower than PHY
  firewire: optimize gap count with 1394b leaf nodes
  firewire: remove unused macro
  firewire: missing newline in printk
  firewire: fw-sbp2: remove unused struct member
  ieee1394: remove old isochronous ABI
  ieee1394: sbp2: change some module parameters from int to bool
  ...
parents 36b77410 7aa48481
What: legacy isochronous ABI of raw1394 (1st generation iso ABI)
Date: June 2007 (scheduled), removed in kernel v2.6.23
Contact: linux1394-devel@lists.sourceforge.net
Description:
The two request types RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN have
been deprecated for quite some time. They are very inefficient as they
come with high interrupt load and several layers of callbacks for each
packet. Because of these deficiencies, the video1394 and dv1394 drivers
and the 3rd-generation isochronous ABI in raw1394 (rawiso) were created.
Users:
libraw1394 users via the long deprecated API raw1394_iso_write,
raw1394_start_iso_write, raw1394_start_iso_rcv, raw1394_stop_iso_rcv
libdc1394, which optionally uses these old libraw1394 calls
alternatively to the more efficient video1394 ABI
...@@ -49,16 +49,6 @@ Who: Adrian Bunk <bunk@stusta.de> ...@@ -49,16 +49,6 @@ Who: Adrian Bunk <bunk@stusta.de>
--------------------------- ---------------------------
What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
When: June 2007
Why: Deprecated in favour of the more efficient and robust rawiso interface.
Affected are applications which use the deprecated part of libraw1394
(raw1394_iso_write, raw1394_start_iso_write, raw1394_start_iso_rcv,
raw1394_stop_iso_rcv) or bypass libraw1394.
Who: Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
---------------------------
What: old NCR53C9x driver What: old NCR53C9x driver
When: October 2007 When: October 2007
Why: Replaced by the much better esp_scsi driver. Actual low-level Why: Replaced by the much better esp_scsi driver. Actual low-level
......
...@@ -336,8 +336,11 @@ fw_card_bm_work(struct work_struct *work) ...@@ -336,8 +336,11 @@ fw_card_bm_work(struct work_struct *work)
} }
pick_me: pick_me:
/* Now figure out what gap count to set. */ /*
if (card->topology_type == FW_TOPOLOGY_A && * Pick a gap count from 1394a table E-1. The table doesn't cover
* the typically much larger 1394b beta repeater delays though.
*/
if (!card->beta_repeaters_present &&
card->root_node->max_hops < ARRAY_SIZE(gap_count_table)) card->root_node->max_hops < ARRAY_SIZE(gap_count_table))
gap_count = gap_count_table[card->root_node->max_hops]; gap_count = gap_count_table[card->root_node->max_hops];
else else
......
...@@ -397,7 +397,7 @@ static int ioctl_send_request(struct client *client, void *buffer) ...@@ -397,7 +397,7 @@ static int ioctl_send_request(struct client *client, void *buffer)
request->tcode & 0x1f, request->tcode & 0x1f,
device->node->node_id, device->node->node_id,
request->generation, request->generation,
device->node->max_speed, device->max_speed,
request->offset, request->offset,
response->response.data, request->length, response->response.data, request->length,
complete_transaction, response); complete_transaction, response);
......
...@@ -401,8 +401,7 @@ static int read_rom(struct fw_device *device, int index, u32 * data) ...@@ -401,8 +401,7 @@ static int read_rom(struct fw_device *device, int index, u32 * data)
offset = 0xfffff0000400ULL + index * 4; offset = 0xfffff0000400ULL + index * 4;
fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST, fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
device->node_id, device->node_id, device->generation, device->max_speed,
device->generation, SCODE_100,
offset, NULL, 4, complete_transaction, &callback_data); offset, NULL, 4, complete_transaction, &callback_data);
wait_for_completion(&callback_data.done); wait_for_completion(&callback_data.done);
...@@ -418,6 +417,8 @@ static int read_bus_info_block(struct fw_device *device) ...@@ -418,6 +417,8 @@ static int read_bus_info_block(struct fw_device *device)
u32 stack[16], sp, key; u32 stack[16], sp, key;
int i, end, length; int i, end, length;
device->max_speed = SCODE_100;
/* First read the bus info block. */ /* First read the bus info block. */
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
...@@ -434,6 +435,33 @@ static int read_bus_info_block(struct fw_device *device) ...@@ -434,6 +435,33 @@ static int read_bus_info_block(struct fw_device *device)
return -1; return -1;
} }
device->max_speed = device->node->max_speed;
/*
* Determine the speed of
* - devices with link speed less than PHY speed,
* - devices with 1394b PHY (unless only connected to 1394a PHYs),
* - all devices if there are 1394b repeaters.
* Note, we cannot use the bus info block's link_spd as starting point
* because some buggy firmwares set it lower than necessary and because
* 1394-1995 nodes do not have the field.
*/
if ((rom[2] & 0x7) < device->max_speed ||
device->max_speed == SCODE_BETA ||
device->card->beta_repeaters_present) {
u32 dummy;
/* for S1600 and S3200 */
if (device->max_speed == SCODE_BETA)
device->max_speed = device->card->link_speed;
while (device->max_speed > SCODE_100) {
if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
break;
device->max_speed--;
}
}
/* /*
* Now parse the config rom. The config rom is a recursive * Now parse the config rom. The config rom is a recursive
* directory structure so we parse it using a stack of * directory structure so we parse it using a stack of
...@@ -680,8 +708,10 @@ static void fw_device_init(struct work_struct *work) ...@@ -680,8 +708,10 @@ static void fw_device_init(struct work_struct *work)
FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
fw_device_shutdown(&device->work.work); fw_device_shutdown(&device->work.work);
else else
fw_notify("created new fw device %s (%d config rom retries)\n", fw_notify("created new fw device %s "
device->device.bus_id, device->config_rom_retries); "(%d config rom retries, S%d00)\n",
device->device.bus_id, device->config_rom_retries,
1 << device->max_speed);
/* /*
* Reschedule the IRM work if we just finished reading the * Reschedule the IRM work if we just finished reading the
......
...@@ -40,6 +40,7 @@ struct fw_device { ...@@ -40,6 +40,7 @@ struct fw_device {
struct fw_node *node; struct fw_node *node;
int node_id; int node_id;
int generation; int generation;
unsigned max_speed;
struct fw_card *card; struct fw_card *card;
struct device device; struct device device;
struct list_head link; struct list_head link;
......
...@@ -1934,12 +1934,12 @@ static int pci_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -1934,12 +1934,12 @@ static int pci_suspend(struct pci_dev *pdev, pm_message_t state)
free_irq(pdev->irq, ohci); free_irq(pdev->irq, ohci);
err = pci_save_state(pdev); err = pci_save_state(pdev);
if (err) { if (err) {
fw_error("pci_save_state failed with %d", err); fw_error("pci_save_state failed\n");
return err; return err;
} }
err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
if (err) { if (err) {
fw_error("pci_set_power_state failed with %d", err); fw_error("pci_set_power_state failed\n");
return err; return err;
} }
...@@ -1955,7 +1955,7 @@ static int pci_resume(struct pci_dev *pdev) ...@@ -1955,7 +1955,7 @@ static int pci_resume(struct pci_dev *pdev)
pci_restore_state(pdev); pci_restore_state(pdev);
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) { if (err) {
fw_error("pci_enable_device failed with %d", err); fw_error("pci_enable_device failed\n");
return err; return err;
} }
......
...@@ -30,10 +30,13 @@ ...@@ -30,10 +30,13 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/blkdev.h>
#include <linux/string.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
...@@ -46,6 +49,18 @@ ...@@ -46,6 +49,18 @@
#include "fw-topology.h" #include "fw-topology.h"
#include "fw-device.h" #include "fw-device.h"
/*
* So far only bridges from Oxford Semiconductor are known to support
* concurrent logins. Depending on firmware, four or two concurrent logins
* are possible on OXFW911 and newer Oxsemi bridges.
*
* Concurrent logins are useful together with cluster filesystems.
*/
static int sbp2_param_exclusive_login = 1;
module_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644);
MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
"(default = Y, use N for concurrent initiators)");
/* I don't know why the SCSI stack doesn't define something like this... */ /* I don't know why the SCSI stack doesn't define something like this... */
typedef void (*scsi_done_fn_t)(struct scsi_cmnd *); typedef void (*scsi_done_fn_t)(struct scsi_cmnd *);
...@@ -154,7 +169,7 @@ struct sbp2_orb { ...@@ -154,7 +169,7 @@ struct sbp2_orb {
#define MANAGEMENT_ORB_LUN(v) ((v)) #define MANAGEMENT_ORB_LUN(v) ((v))
#define MANAGEMENT_ORB_FUNCTION(v) ((v) << 16) #define MANAGEMENT_ORB_FUNCTION(v) ((v) << 16)
#define MANAGEMENT_ORB_RECONNECT(v) ((v) << 20) #define MANAGEMENT_ORB_RECONNECT(v) ((v) << 20)
#define MANAGEMENT_ORB_EXCLUSIVE ((1) << 28) #define MANAGEMENT_ORB_EXCLUSIVE(v) ((v) ? 1 << 28 : 0)
#define MANAGEMENT_ORB_REQUEST_FORMAT(v) ((v) << 29) #define MANAGEMENT_ORB_REQUEST_FORMAT(v) ((v) << 29)
#define MANAGEMENT_ORB_NOTIFY ((1) << 31) #define MANAGEMENT_ORB_NOTIFY ((1) << 31)
...@@ -205,9 +220,8 @@ struct sbp2_command_orb { ...@@ -205,9 +220,8 @@ struct sbp2_command_orb {
scsi_done_fn_t done; scsi_done_fn_t done;
struct fw_unit *unit; struct fw_unit *unit;
struct sbp2_pointer page_table[SG_ALL]; struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8)));
dma_addr_t page_table_bus; dma_addr_t page_table_bus;
dma_addr_t request_buffer_bus;
}; };
/* /*
...@@ -347,8 +361,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit, ...@@ -347,8 +361,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit,
spin_unlock_irqrestore(&device->card->lock, flags); spin_unlock_irqrestore(&device->card->lock, flags);
fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST, fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
node_id, generation, node_id, generation, device->max_speed, offset,
device->node->max_speed, offset,
&orb->pointer, sizeof(orb->pointer), &orb->pointer, sizeof(orb->pointer),
complete_transaction, orb); complete_transaction, orb);
} }
...@@ -383,7 +396,7 @@ static void ...@@ -383,7 +396,7 @@ static void
complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
{ {
struct sbp2_management_orb *orb = struct sbp2_management_orb *orb =
(struct sbp2_management_orb *)base_orb; container_of(base_orb, struct sbp2_management_orb, base);
if (status) if (status)
memcpy(&orb->status, status, sizeof(*status)); memcpy(&orb->status, status, sizeof(*status));
...@@ -403,21 +416,11 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, ...@@ -403,21 +416,11 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
if (orb == NULL) if (orb == NULL)
return -ENOMEM; return -ENOMEM;
/*
* The sbp2 device is going to send a block read request to
* read out the request from host memory, so map it for dma.
*/
orb->base.request_bus =
dma_map_single(device->card->device, &orb->request,
sizeof(orb->request), DMA_TO_DEVICE);
if (dma_mapping_error(orb->base.request_bus))
goto out;
orb->response_bus = orb->response_bus =
dma_map_single(device->card->device, &orb->response, dma_map_single(device->card->device, &orb->response,
sizeof(orb->response), DMA_FROM_DEVICE); sizeof(orb->response), DMA_FROM_DEVICE);
if (dma_mapping_error(orb->response_bus)) if (dma_mapping_error(orb->response_bus))
goto out; goto fail_mapping_response;
orb->request.response.high = 0; orb->request.response.high = 0;
orb->request.response.low = orb->response_bus; orb->request.response.low = orb->response_bus;
...@@ -432,14 +435,9 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, ...@@ -432,14 +435,9 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
orb->request.status_fifo.high = sd->address_handler.offset >> 32; orb->request.status_fifo.high = sd->address_handler.offset >> 32;
orb->request.status_fifo.low = sd->address_handler.offset; orb->request.status_fifo.low = sd->address_handler.offset;
/*
* FIXME: Yeah, ok this isn't elegant, we hardwire exclusive
* login and 1 second reconnect time. The reconnect setting
* is probably fine, but the exclusive login should be an option.
*/
if (function == SBP2_LOGIN_REQUEST) { if (function == SBP2_LOGIN_REQUEST) {
orb->request.misc |= orb->request.misc |=
MANAGEMENT_ORB_EXCLUSIVE | MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login) |
MANAGEMENT_ORB_RECONNECT(0); MANAGEMENT_ORB_RECONNECT(0);
} }
...@@ -448,6 +446,12 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, ...@@ -448,6 +446,12 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
init_completion(&orb->done); init_completion(&orb->done);
orb->base.callback = complete_management_orb; orb->base.callback = complete_management_orb;
orb->base.request_bus =
dma_map_single(device->card->device, &orb->request,
sizeof(orb->request), DMA_TO_DEVICE);
if (dma_mapping_error(orb->base.request_bus))
goto fail_mapping_request;
sbp2_send_orb(&orb->base, unit, sbp2_send_orb(&orb->base, unit,
node_id, generation, sd->management_agent_address); node_id, generation, sd->management_agent_address);
...@@ -479,9 +483,10 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, ...@@ -479,9 +483,10 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
out: out:
dma_unmap_single(device->card->device, orb->base.request_bus, dma_unmap_single(device->card->device, orb->base.request_bus,
sizeof(orb->request), DMA_TO_DEVICE); sizeof(orb->request), DMA_TO_DEVICE);
fail_mapping_request:
dma_unmap_single(device->card->device, orb->response_bus, dma_unmap_single(device->card->device, orb->response_bus,
sizeof(orb->response), DMA_FROM_DEVICE); sizeof(orb->response), DMA_FROM_DEVICE);
fail_mapping_response:
if (response) if (response)
fw_memcpy_from_be32(response, fw_memcpy_from_be32(response,
orb->response, sizeof(orb->response)); orb->response, sizeof(orb->response));
...@@ -511,7 +516,7 @@ static int sbp2_agent_reset(struct fw_unit *unit) ...@@ -511,7 +516,7 @@ static int sbp2_agent_reset(struct fw_unit *unit)
return -ENOMEM; return -ENOMEM;
fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
sd->node_id, sd->generation, SCODE_400, sd->node_id, sd->generation, device->max_speed,
sd->command_block_agent_address + SBP2_AGENT_RESET, sd->command_block_agent_address + SBP2_AGENT_RESET,
&zero, sizeof(zero), complete_agent_reset_write, t); &zero, sizeof(zero), complete_agent_reset_write, t);
...@@ -521,17 +526,15 @@ static int sbp2_agent_reset(struct fw_unit *unit) ...@@ -521,17 +526,15 @@ static int sbp2_agent_reset(struct fw_unit *unit)
static void sbp2_reconnect(struct work_struct *work); static void sbp2_reconnect(struct work_struct *work);
static struct scsi_host_template scsi_driver_template; static struct scsi_host_template scsi_driver_template;
static void static void release_sbp2_device(struct kref *kref)
release_sbp2_device(struct kref *kref)
{ {
struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref); struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref);
struct Scsi_Host *host = struct Scsi_Host *host =
container_of((void *)sd, struct Scsi_Host, hostdata[0]); container_of((void *)sd, struct Scsi_Host, hostdata[0]);
scsi_remove_host(host);
sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation, sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation,
SBP2_LOGOUT_REQUEST, sd->login_id, NULL); SBP2_LOGOUT_REQUEST, sd->login_id, NULL);
scsi_remove_host(host);
fw_core_remove_address_handler(&sd->address_handler); fw_core_remove_address_handler(&sd->address_handler);
fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id); fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id);
put_device(&sd->unit->device); put_device(&sd->unit->device);
...@@ -833,7 +836,8 @@ sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) ...@@ -833,7 +836,8 @@ sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data)
static void static void
complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
{ {
struct sbp2_command_orb *orb = (struct sbp2_command_orb *)base_orb; struct sbp2_command_orb *orb =
container_of(base_orb, struct sbp2_command_orb, base);
struct fw_unit *unit = orb->unit; struct fw_unit *unit = orb->unit;
struct fw_device *device = fw_device(unit->device.parent); struct fw_device *device = fw_device(unit->device.parent);
struct scatterlist *sg; struct scatterlist *sg;
...@@ -880,12 +884,7 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) ...@@ -880,12 +884,7 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
if (orb->page_table_bus != 0) if (orb->page_table_bus != 0)
dma_unmap_single(device->card->device, orb->page_table_bus, dma_unmap_single(device->card->device, orb->page_table_bus,
sizeof(orb->page_table_bus), DMA_TO_DEVICE); sizeof(orb->page_table), DMA_TO_DEVICE);
if (orb->request_buffer_bus != 0)
dma_unmap_single(device->card->device, orb->request_buffer_bus,
sizeof(orb->request_buffer_bus),
DMA_FROM_DEVICE);
orb->cmd->result = result; orb->cmd->result = result;
orb->done(orb->cmd); orb->done(orb->cmd);
...@@ -900,7 +899,6 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) ...@@ -900,7 +899,6 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
struct fw_device *device = fw_device(unit->device.parent); struct fw_device *device = fw_device(unit->device.parent);
struct scatterlist *sg; struct scatterlist *sg;
int sg_len, l, i, j, count; int sg_len, l, i, j, count;
size_t size;
dma_addr_t sg_addr; dma_addr_t sg_addr;
sg = (struct scatterlist *)orb->cmd->request_buffer; sg = (struct scatterlist *)orb->cmd->request_buffer;
...@@ -935,6 +933,11 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) ...@@ -935,6 +933,11 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
sg_len = sg_dma_len(sg + i); sg_len = sg_dma_len(sg + i);
sg_addr = sg_dma_address(sg + i); sg_addr = sg_dma_address(sg + i);
while (sg_len) { while (sg_len) {
/* FIXME: This won't get us out of the pinch. */
if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
fw_error("page table overflow\n");
goto fail_page_table;
}
l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH); l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
orb->page_table[j].low = sg_addr; orb->page_table[j].low = sg_addr;
orb->page_table[j].high = (l << 16); orb->page_table[j].high = (l << 16);
...@@ -944,7 +947,13 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) ...@@ -944,7 +947,13 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
} }
} }
size = sizeof(orb->page_table[0]) * j; fw_memcpy_to_be32(orb->page_table, orb->page_table,
sizeof(orb->page_table[0]) * j);
orb->page_table_bus =
dma_map_single(device->card->device, orb->page_table,
sizeof(orb->page_table), DMA_TO_DEVICE);
if (dma_mapping_error(orb->page_table_bus))
goto fail_page_table;
/* /*
* The data_descriptor pointer is the one case where we need * The data_descriptor pointer is the one case where we need
...@@ -953,20 +962,12 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) ...@@ -953,20 +962,12 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
* initiator (i.e. us), but data_descriptor can refer to data * initiator (i.e. us), but data_descriptor can refer to data
* on other nodes so we need to put our ID in descriptor.high. * on other nodes so we need to put our ID in descriptor.high.
*/ */
orb->page_table_bus =
dma_map_single(device->card->device, orb->page_table,
size, DMA_TO_DEVICE);
if (dma_mapping_error(orb->page_table_bus))
goto fail_page_table;
orb->request.data_descriptor.high = sd->address_high; orb->request.data_descriptor.high = sd->address_high;
orb->request.data_descriptor.low = orb->page_table_bus; orb->request.data_descriptor.low = orb->page_table_bus;
orb->request.misc |= orb->request.misc |=
COMMAND_ORB_PAGE_TABLE_PRESENT | COMMAND_ORB_PAGE_TABLE_PRESENT |
COMMAND_ORB_DATA_SIZE(j); COMMAND_ORB_DATA_SIZE(j);
fw_memcpy_to_be32(orb->page_table, orb->page_table, size);
return 0; return 0;
fail_page_table: fail_page_table:
...@@ -991,7 +992,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) ...@@ -991,7 +992,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
* transfer direction not handled. * transfer direction not handled.
*/ */
if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) { if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
fw_error("Cannot handle DMA_BIDIRECTIONAL - rejecting command"); fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
cmd->result = DID_ERROR << 16; cmd->result = DID_ERROR << 16;
done(cmd); done(cmd);
return 0; return 0;
...@@ -1005,11 +1006,6 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) ...@@ -1005,11 +1006,6 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
/* Initialize rcode to something not RCODE_COMPLETE. */ /* Initialize rcode to something not RCODE_COMPLETE. */
orb->base.rcode = -1; orb->base.rcode = -1;
orb->base.request_bus =
dma_map_single(device->card->device, &orb->request,
sizeof(orb->request), DMA_TO_DEVICE);
if (dma_mapping_error(orb->base.request_bus))
goto fail_mapping;
orb->unit = unit; orb->unit = unit;
orb->done = done; orb->done = done;
...@@ -1024,8 +1020,8 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) ...@@ -1024,8 +1020,8 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
* if we set this to max_speed + 7, we get the right value. * if we set this to max_speed + 7, we get the right value.
*/ */
orb->request.misc = orb->request.misc =
COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) | COMMAND_ORB_MAX_PAYLOAD(device->max_speed + 7) |
COMMAND_ORB_SPEED(device->node->max_speed) | COMMAND_ORB_SPEED(device->max_speed) |
COMMAND_ORB_NOTIFY; COMMAND_ORB_NOTIFY;
if (cmd->sc_data_direction == DMA_FROM_DEVICE) if (cmd->sc_data_direction == DMA_FROM_DEVICE)
...@@ -1036,7 +1032,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) ...@@ -1036,7 +1032,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA); COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA);
if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0) if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0)
goto fail_map_payload; goto fail_mapping;
fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request)); fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
...@@ -1045,15 +1041,17 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) ...@@ -1045,15 +1041,17 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd)); memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
orb->base.callback = complete_command_orb; orb->base.callback = complete_command_orb;
orb->base.request_bus =
dma_map_single(device->card->device, &orb->request,
sizeof(orb->request), DMA_TO_DEVICE);
if (dma_mapping_error(orb->base.request_bus))
goto fail_mapping;
sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation, sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation,
sd->command_block_agent_address + SBP2_ORB_POINTER); sd->command_block_agent_address + SBP2_ORB_POINTER);
return 0; return 0;
fail_map_payload:
dma_unmap_single(device->card->device, orb->base.request_bus,
sizeof(orb->request), DMA_TO_DEVICE);
fail_mapping: fail_mapping:
kfree(orb); kfree(orb);
fail_alloc: fail_alloc:
...@@ -1087,7 +1085,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) ...@@ -1087,7 +1085,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
fw_notify("setting fix_capacity for %s\n", unit->device.bus_id); fw_notify("setting fix_capacity for %s\n", unit->device.bus_id);
sdev->fix_capacity = 1; sdev->fix_capacity = 1;
} }
if (sd->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
return 0; return 0;
} }
......
...@@ -135,17 +135,17 @@ static void update_hop_count(struct fw_node *node) ...@@ -135,17 +135,17 @@ static void update_hop_count(struct fw_node *node)
int i; int i;
for (i = 0; i < node->port_count; i++) { for (i = 0; i < node->port_count; i++) {
if (node->ports[i].node == NULL) if (node->ports[i] == NULL)
continue; continue;
if (node->ports[i].node->max_hops > max_child_hops) if (node->ports[i]->max_hops > max_child_hops)
max_child_hops = node->ports[i].node->max_hops; max_child_hops = node->ports[i]->max_hops;
if (node->ports[i].node->max_depth > depths[0]) { if (node->ports[i]->max_depth > depths[0]) {
depths[1] = depths[0]; depths[1] = depths[0];
depths[0] = node->ports[i].node->max_depth; depths[0] = node->ports[i]->max_depth;
} else if (node->ports[i].node->max_depth > depths[1]) } else if (node->ports[i]->max_depth > depths[1])
depths[1] = node->ports[i].node->max_depth; depths[1] = node->ports[i]->max_depth;
} }
node->max_depth = depths[0] + 1; node->max_depth = depths[0] + 1;
...@@ -172,7 +172,8 @@ static struct fw_node *build_tree(struct fw_card *card, ...@@ -172,7 +172,8 @@ static struct fw_node *build_tree(struct fw_card *card,
struct list_head stack, *h; struct list_head stack, *h;
u32 *next_sid, *end, q; u32 *next_sid, *end, q;
int i, port_count, child_port_count, phy_id, parent_count, stack_depth; int i, port_count, child_port_count, phy_id, parent_count, stack_depth;
int gap_count, topology_type; int gap_count;
bool beta_repeaters_present;
local_node = NULL; local_node = NULL;
node = NULL; node = NULL;
...@@ -182,7 +183,7 @@ static struct fw_node *build_tree(struct fw_card *card, ...@@ -182,7 +183,7 @@ static struct fw_node *build_tree(struct fw_card *card,
phy_id = 0; phy_id = 0;
irm_node = NULL; irm_node = NULL;
gap_count = SELF_ID_GAP_COUNT(*sid); gap_count = SELF_ID_GAP_COUNT(*sid);
topology_type = 0; beta_repeaters_present = false;
while (sid < end) { while (sid < end) {
next_sid = count_ports(sid, &port_count, &child_port_count); next_sid = count_ports(sid, &port_count, &child_port_count);
...@@ -214,7 +215,7 @@ static struct fw_node *build_tree(struct fw_card *card, ...@@ -214,7 +215,7 @@ static struct fw_node *build_tree(struct fw_card *card,
node = fw_node_create(q, port_count, card->color); node = fw_node_create(q, port_count, card->color);
if (node == NULL) { if (node == NULL) {
fw_error("Out of memory while building topology."); fw_error("Out of memory while building topology.\n");
return NULL; return NULL;
} }
...@@ -224,11 +225,6 @@ static struct fw_node *build_tree(struct fw_card *card, ...@@ -224,11 +225,6 @@ static struct fw_node *build_tree(struct fw_card *card,
if (SELF_ID_CONTENDER(q)) if (SELF_ID_CONTENDER(q))
irm_node = node; irm_node = node;
if (node->phy_speed == SCODE_BETA)
topology_type |= FW_TOPOLOGY_B;
else
topology_type |= FW_TOPOLOGY_A;
parent_count = 0; parent_count = 0;
for (i = 0; i < port_count; i++) { for (i = 0; i < port_count; i++) {
...@@ -249,12 +245,12 @@ static struct fw_node *build_tree(struct fw_card *card, ...@@ -249,12 +245,12 @@ static struct fw_node *build_tree(struct fw_card *card,
break; break;
case SELFID_PORT_CHILD: case SELFID_PORT_CHILD:
node->ports[i].node = child; node->ports[i] = child;
/* /*
* Fix up parent reference for this * Fix up parent reference for this
* child node. * child node.
*/ */
child->ports[child->color].node = node; child->ports[child->color] = node;
child->color = card->color; child->color = card->color;
child = fw_node(child->link.next); child = fw_node(child->link.next);
break; break;
...@@ -278,6 +274,10 @@ static struct fw_node *build_tree(struct fw_card *card, ...@@ -278,6 +274,10 @@ static struct fw_node *build_tree(struct fw_card *card,
list_add_tail(&node->link, &stack); list_add_tail(&node->link, &stack);
stack_depth += 1 - child_port_count; stack_depth += 1 - child_port_count;
if (node->phy_speed == SCODE_BETA &&
parent_count + child_port_count > 1)
beta_repeaters_present = true;
/* /*
* If all PHYs does not report the same gap count * If all PHYs does not report the same gap count
* setting, we fall back to 63 which will force a gap * setting, we fall back to 63 which will force a gap
...@@ -295,7 +295,7 @@ static struct fw_node *build_tree(struct fw_card *card, ...@@ -295,7 +295,7 @@ static struct fw_node *build_tree(struct fw_card *card,
card->root_node = node; card->root_node = node;
card->irm_node = irm_node; card->irm_node = irm_node;
card->gap_count = gap_count; card->gap_count = gap_count;
card->topology_type = topology_type; card->beta_repeaters_present = beta_repeaters_present;
return local_node; return local_node;
} }
...@@ -321,7 +321,7 @@ for_each_fw_node(struct fw_card *card, struct fw_node *root, ...@@ -321,7 +321,7 @@ for_each_fw_node(struct fw_card *card, struct fw_node *root,
node->color = card->color; node->color = card->color;
for (i = 0; i < node->port_count; i++) { for (i = 0; i < node->port_count; i++) {
child = node->ports[i].node; child = node->ports[i];
if (!child) if (!child)
continue; continue;
if (child->color == card->color) if (child->color == card->color)
...@@ -382,11 +382,11 @@ static void move_tree(struct fw_node *node0, struct fw_node *node1, int port) ...@@ -382,11 +382,11 @@ static void move_tree(struct fw_node *node0, struct fw_node *node1, int port)
struct fw_node *tree; struct fw_node *tree;
int i; int i;
tree = node1->ports[port].node; tree = node1->ports[port];
node0->ports[port].node = tree; node0->ports[port] = tree;
for (i = 0; i < tree->port_count; i++) { for (i = 0; i < tree->port_count; i++) {
if (tree->ports[i].node == node1) { if (tree->ports[i] == node1) {
tree->ports[i].node = node0; tree->ports[i] = node0;
break; break;
} }
} }
...@@ -437,19 +437,17 @@ update_tree(struct fw_card *card, struct fw_node *root) ...@@ -437,19 +437,17 @@ update_tree(struct fw_card *card, struct fw_node *root)
card->irm_node = node0; card->irm_node = node0;
for (i = 0; i < node0->port_count; i++) { for (i = 0; i < node0->port_count; i++) {
if (node0->ports[i].node && node1->ports[i].node) { if (node0->ports[i] && node1->ports[i]) {
/* /*
* This port didn't change, queue the * This port didn't change, queue the
* connected node for further * connected node for further
* investigation. * investigation.
*/ */
if (node0->ports[i].node->color == card->color) if (node0->ports[i]->color == card->color)
continue; continue;
list_add_tail(&node0->ports[i].node->link, list_add_tail(&node0->ports[i]->link, &list0);
&list0); list_add_tail(&node1->ports[i]->link, &list1);
list_add_tail(&node1->ports[i].node->link, } else if (node0->ports[i]) {
&list1);
} else if (node0->ports[i].node) {
/* /*
* The nodes connected here were * The nodes connected here were
* unplugged; unref the lost nodes and * unplugged; unref the lost nodes and
...@@ -457,10 +455,10 @@ update_tree(struct fw_card *card, struct fw_node *root) ...@@ -457,10 +455,10 @@ update_tree(struct fw_card *card, struct fw_node *root)
* them. * them.
*/ */
for_each_fw_node(card, node0->ports[i].node, for_each_fw_node(card, node0->ports[i],
report_lost_node); report_lost_node);
node0->ports[i].node = NULL; node0->ports[i] = NULL;
} else if (node1->ports[i].node) { } else if (node1->ports[i]) {
/* /*
* One or more node were connected to * One or more node were connected to
* this port. Move the new nodes into * this port. Move the new nodes into
...@@ -468,7 +466,7 @@ update_tree(struct fw_card *card, struct fw_node *root) ...@@ -468,7 +466,7 @@ update_tree(struct fw_card *card, struct fw_node *root)
* callbacks for them. * callbacks for them.
*/ */
move_tree(node0, node1, i); move_tree(node0, node1, i);
for_each_fw_node(card, node0->ports[i].node, for_each_fw_node(card, node0->ports[i],
report_found_node); report_found_node);
} }
} }
......
...@@ -19,12 +19,6 @@ ...@@ -19,12 +19,6 @@
#ifndef __fw_topology_h #ifndef __fw_topology_h
#define __fw_topology_h #define __fw_topology_h
enum {
FW_TOPOLOGY_A = 0x01,
FW_TOPOLOGY_B = 0x02,
FW_TOPOLOGY_MIXED = 0x03,
};
enum { enum {
FW_NODE_CREATED = 0x00, FW_NODE_CREATED = 0x00,
FW_NODE_UPDATED = 0x01, FW_NODE_UPDATED = 0x01,
...@@ -33,21 +27,16 @@ enum { ...@@ -33,21 +27,16 @@ enum {
FW_NODE_LINK_OFF = 0x04, FW_NODE_LINK_OFF = 0x04,
}; };
struct fw_port {
struct fw_node *node;
unsigned speed : 3; /* S100, S200, ... S3200 */
};
struct fw_node { struct fw_node {
u16 node_id; u16 node_id;
u8 color; u8 color;
u8 port_count; u8 port_count;
unsigned link_on : 1; u8 link_on : 1;
unsigned initiated_reset : 1; u8 initiated_reset : 1;
unsigned b_path : 1; u8 b_path : 1;
u8 phy_speed : 3; /* As in the self ID packet. */ u8 phy_speed : 2; /* As in the self ID packet. */
u8 max_speed : 5; /* Minimum of all phy-speeds and port speeds on u8 max_speed : 2; /* Minimum of all phy-speeds on the path from the
* the path from the local node to this node. */ * local node to this node. */
u8 max_depth : 4; /* Maximum depth to any leaf node */ u8 max_depth : 4; /* Maximum depth to any leaf node */
u8 max_hops : 4; /* Max hops in this sub tree */ u8 max_hops : 4; /* Max hops in this sub tree */
atomic_t ref_count; atomic_t ref_count;
...@@ -58,7 +47,7 @@ struct fw_node { ...@@ -58,7 +47,7 @@ struct fw_node {
/* Upper layer specific data. */ /* Upper layer specific data. */
void *data; void *data;
struct fw_port ports[0]; struct fw_node *ports[0];
}; };
static inline struct fw_node * static inline struct fw_node *
......
...@@ -81,7 +81,6 @@ ...@@ -81,7 +81,6 @@
#define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args) #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
#define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) #define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
#define fw_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args)
static inline void static inline void
fw_memcpy_from_be32(void *_dst, void *_src, size_t size) fw_memcpy_from_be32(void *_dst, void *_src, size_t size)
...@@ -246,7 +245,7 @@ struct fw_card { ...@@ -246,7 +245,7 @@ struct fw_card {
struct fw_node *irm_node; struct fw_node *irm_node;
int color; int color;
int gap_count; int gap_count;
int topology_type; bool beta_repeaters_present;
int index; int index;
......
...@@ -2280,7 +2280,7 @@ static void dv1394_remove_host(struct hpsb_host *host) ...@@ -2280,7 +2280,7 @@ static void dv1394_remove_host(struct hpsb_host *host)
} while (video); } while (video);
if (found_ohci_card) if (found_ohci_card)
class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR, device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_DV1394 * 16 + (host->id << 2))); IEEE1394_MINOR_BLOCK_DV1394 * 16 + (host->id << 2)));
} }
...@@ -2295,9 +2295,9 @@ static void dv1394_add_host(struct hpsb_host *host) ...@@ -2295,9 +2295,9 @@ static void dv1394_add_host(struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata; ohci = (struct ti_ohci *)host->hostdata;
class_device_create(hpsb_protocol_class, NULL, MKDEV( device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
NULL, "dv1394-%d", id); "dv1394-%d", id);
dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE); dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT); dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
......
...@@ -599,9 +599,7 @@ static void ether1394_add_host(struct hpsb_host *host) ...@@ -599,9 +599,7 @@ static void ether1394_add_host(struct hpsb_host *host)
} }
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &host->device);
/* This used to be &host->device in Linux 2.6.20 and before. */
SET_NETDEV_DEV(dev, host->device.parent);
priv = netdev_priv(dev); priv = netdev_priv(dev);
INIT_LIST_HEAD(&priv->ip_node_list); INIT_LIST_HEAD(&priv->ip_node_list);
......
...@@ -483,37 +483,6 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, ...@@ -483,37 +483,6 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
return retval; return retval;
} }
/**
* hpsb_listen_channel - enable receving a certain isochronous channel
*
* Reception is handled through the @hl's iso_receive op.
*/
int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel)
{
if (channel > 63) {
HPSB_ERR("%s called with invalid channel", __FUNCTION__);
return -EINVAL;
}
if (host->iso_listen_count[channel]++ == 0)
return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
return 0;
}
/**
* hpsb_unlisten_channel - disable receving a certain isochronous channel
*/
void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel)
{
if (channel > 63) {
HPSB_ERR("%s called with invalid channel", __FUNCTION__);
return;
}
if (--host->iso_listen_count[channel] == 0)
host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel);
}
static void init_hpsb_highlevel(struct hpsb_host *host) static void init_hpsb_highlevel(struct hpsb_host *host)
{ {
INIT_LIST_HEAD(&dummy_zero_addr.host_list); INIT_LIST_HEAD(&dummy_zero_addr.host_list);
...@@ -570,20 +539,6 @@ void highlevel_host_reset(struct hpsb_host *host) ...@@ -570,20 +539,6 @@ void highlevel_host_reset(struct hpsb_host *host)
read_unlock_irqrestore(&hl_irqs_lock, flags); read_unlock_irqrestore(&hl_irqs_lock, flags);
} }
void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length)
{
unsigned long flags;
struct hpsb_highlevel *hl;
int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f;
read_lock_irqsave(&hl_irqs_lock, flags);
list_for_each_entry(hl, &hl_irqs, irq_list) {
if (hl->iso_receive)
hl->iso_receive(host, channel, data, length);
}
read_unlock_irqrestore(&hl_irqs_lock, flags);
}
void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
void *data, size_t length) void *data, size_t length)
{ {
......
...@@ -26,9 +26,7 @@ struct hpsb_address_serve { ...@@ -26,9 +26,7 @@ struct hpsb_address_serve {
struct hpsb_highlevel { struct hpsb_highlevel {
const char *name; const char *name;
/* Any of the following pointers can legally be NULL, except for /* Any of the following pointers can legally be NULL. */
* iso_receive which can only be NULL when you don't request
* channels. */
/* New host initialized. Will also be called during /* New host initialized. Will also be called during
* hpsb_register_highlevel for all hosts already installed. */ * hpsb_register_highlevel for all hosts already installed. */
...@@ -43,13 +41,6 @@ struct hpsb_highlevel { ...@@ -43,13 +41,6 @@ struct hpsb_highlevel {
* You can not expect to be able to do stock hpsb_reads. */ * 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);
/* A write request was received on either the FCP_COMMAND (direction = /* A write request was received on either the FCP_COMMAND (direction =
* 0) or the FCP_RESPONSE (direction = 1) register. The cts arg * 0) or the FCP_RESPONSE (direction = 1) register. The cts arg
* contains the cts field (first byte of data). */ * contains the cts field (first byte of data). */
...@@ -109,7 +100,6 @@ int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, ...@@ -109,7 +100,6 @@ int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store, int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
u16 flags); u16 flags);
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 highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
void *data, size_t length); void *data, size_t length);
...@@ -125,10 +115,6 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, ...@@ -125,10 +115,6 @@ 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, int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
u64 start); u64 start);
int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel);
void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel);
void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host); void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
......
...@@ -154,15 +154,16 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, ...@@ -154,15 +154,16 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device)); memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
h->device.parent = dev; h->device.parent = dev;
set_dev_node(&h->device, dev_to_node(dev));
snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id); snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
h->class_dev.dev = &h->device; h->host_dev.parent = &h->device;
h->class_dev.class = &hpsb_host_class; h->host_dev.class = &hpsb_host_class;
snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id); snprintf(h->host_dev.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
if (device_register(&h->device)) if (device_register(&h->device))
goto fail; goto fail;
if (class_device_register(&h->class_dev)) { if (device_register(&h->host_dev)) {
device_unregister(&h->device); device_unregister(&h->device);
goto fail; goto fail;
} }
...@@ -202,7 +203,7 @@ void hpsb_remove_host(struct hpsb_host *host) ...@@ -202,7 +203,7 @@ void hpsb_remove_host(struct hpsb_host *host)
host->driver = &dummy_driver; host->driver = &dummy_driver;
highlevel_remove_host(host); highlevel_remove_host(host);
class_device_unregister(&host->class_dev); device_unregister(&host->host_dev);
device_unregister(&host->device); device_unregister(&host->device);
} }
......
...@@ -28,8 +28,6 @@ struct hpsb_host { ...@@ -28,8 +28,6 @@ struct hpsb_host {
struct timer_list timeout; struct timer_list timeout;
unsigned long timeout_interval; unsigned long timeout_interval;
unsigned char iso_listen_count[64];
int node_count; /* number of identified nodes on this bus */ int node_count; /* number of identified nodes on this bus */
int selfid_count; /* total number of SelfIDs received */ int selfid_count; /* total number of SelfIDs received */
int nodes_active; /* number of nodes with active link layer */ int nodes_active; /* number of nodes with active link layer */
...@@ -57,7 +55,7 @@ struct hpsb_host { ...@@ -57,7 +55,7 @@ struct hpsb_host {
struct hpsb_host_driver *driver; struct hpsb_host_driver *driver;
struct pci_dev *pdev; struct pci_dev *pdev;
struct device device; struct device device;
struct class_device class_dev; struct device host_dev;
struct delayed_work delayed_reset; struct delayed_work delayed_reset;
unsigned config_roms:31; unsigned config_roms:31;
...@@ -99,12 +97,6 @@ enum devctl_cmd { ...@@ -99,12 +97,6 @@ enum devctl_cmd {
/* Cancel all outstanding async requests without resetting the bus. /* Cancel all outstanding async requests without resetting the bus.
* Return void. */ * Return void. */
CANCEL_REQUESTS, CANCEL_REQUESTS,
/* Start or stop receiving isochronous channel in arg. Return void.
* This acts as an optimization hint, hosts are not required not to
* listen on unrequested channels. */
ISO_LISTEN_CHANNEL,
ISO_UNLISTEN_CHANNEL
}; };
enum isoctl_cmd { enum isoctl_cmd {
......
...@@ -1028,11 +1028,6 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, ...@@ -1028,11 +1028,6 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
handle_incoming_packet(host, tcode, data, size, write_acked); handle_incoming_packet(host, tcode, data, size, write_acked);
break; break;
case TCODE_ISO_DATA:
highlevel_iso_receive(host, data, size);
break;
case TCODE_CYCLE_START: case TCODE_CYCLE_START:
/* simply ignore this packet if it is passed on */ /* simply ignore this packet if it is passed on */
break; break;
...@@ -1316,7 +1311,6 @@ EXPORT_SYMBOL(hpsb_make_streampacket); ...@@ -1316,7 +1311,6 @@ EXPORT_SYMBOL(hpsb_make_streampacket);
EXPORT_SYMBOL(hpsb_make_lockpacket); EXPORT_SYMBOL(hpsb_make_lockpacket);
EXPORT_SYMBOL(hpsb_make_lock64packet); EXPORT_SYMBOL(hpsb_make_lock64packet);
EXPORT_SYMBOL(hpsb_make_phypacket); EXPORT_SYMBOL(hpsb_make_phypacket);
EXPORT_SYMBOL(hpsb_make_isopacket);
EXPORT_SYMBOL(hpsb_read); EXPORT_SYMBOL(hpsb_read);
EXPORT_SYMBOL(hpsb_write); EXPORT_SYMBOL(hpsb_write);
EXPORT_SYMBOL(hpsb_packet_success); EXPORT_SYMBOL(hpsb_packet_success);
...@@ -1327,8 +1321,6 @@ EXPORT_SYMBOL(hpsb_unregister_highlevel); ...@@ -1327,8 +1321,6 @@ EXPORT_SYMBOL(hpsb_unregister_highlevel);
EXPORT_SYMBOL(hpsb_register_addrspace); EXPORT_SYMBOL(hpsb_register_addrspace);
EXPORT_SYMBOL(hpsb_unregister_addrspace); EXPORT_SYMBOL(hpsb_unregister_addrspace);
EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace); EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace);
EXPORT_SYMBOL(hpsb_listen_channel);
EXPORT_SYMBOL(hpsb_unlisten_channel);
EXPORT_SYMBOL(hpsb_get_hostinfo); EXPORT_SYMBOL(hpsb_get_hostinfo);
EXPORT_SYMBOL(hpsb_create_hostinfo); EXPORT_SYMBOL(hpsb_create_hostinfo);
EXPORT_SYMBOL(hpsb_destroy_hostinfo); EXPORT_SYMBOL(hpsb_destroy_hostinfo);
......
...@@ -24,9 +24,8 @@ struct hpsb_packet { ...@@ -24,9 +24,8 @@ struct hpsb_packet {
nodeid_t node_id; nodeid_t node_id;
/* Async and Iso types should be clear, raw means send-as-is, do not /* hpsb_raw = send as-is, do not CRC (but still byte-swap it) */
* CRC! Byte swapping shall still be done in this case. */ enum { hpsb_async, hpsb_raw } __attribute__((packed)) type;
enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
/* Okay, this is core internal and a no care for hosts. /* Okay, this is core internal and a no care for hosts.
* queued = queued for sending * queued = queued for sending
...@@ -37,7 +36,7 @@ struct hpsb_packet { ...@@ -37,7 +36,7 @@ struct hpsb_packet {
hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
} __attribute__((packed)) state; } __attribute__((packed)) state;
/* These are core internal. */ /* These are core-internal. */
signed char tlabel; signed char tlabel;
signed char ack_code; signed char ack_code;
unsigned char tcode; unsigned char tcode;
...@@ -62,11 +61,15 @@ struct hpsb_packet { ...@@ -62,11 +61,15 @@ struct hpsb_packet {
/* Store jiffies for implementing bus timeouts. */ /* Store jiffies for implementing bus timeouts. */
unsigned long sendtime; unsigned long sendtime;
/* Sizes are in bytes. *data can be DMA-mapped. */ /* Core-internal. */
size_t allocated_data_size; /* as allocated */ size_t allocated_data_size; /* as allocated */
/* Sizes are in bytes. To be set by caller of hpsb_alloc_packet. */
size_t data_size; /* as filled in */ size_t data_size; /* as filled in */
size_t header_size; /* as filled in, not counting the CRC */ size_t header_size; /* as filled in, not counting the CRC */
quadlet_t *data;
/* Buffers */
quadlet_t *data; /* can be DMA-mapped */
quadlet_t header[5]; quadlet_t header[5];
quadlet_t embedded_data[0]; /* keep as last member */ quadlet_t embedded_data[0]; /* keep as last member */
}; };
......
...@@ -89,18 +89,6 @@ static void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode, ...@@ -89,18 +89,6 @@ static void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode,
packet->expect_response = 1; packet->expect_response = 1;
} }
static void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
int tag, int sync)
{
packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
| (TCODE_ISO_DATA << 4) | sync;
packet->header_size = 4;
packet->data_size = length;
packet->type = hpsb_iso;
packet->tcode = TCODE_ISO_DATA;
}
static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data) static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
{ {
packet->header[0] = data; packet->header[0] = data;
...@@ -491,24 +479,6 @@ struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data) ...@@ -491,24 +479,6 @@ struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data)
return p; return p;
} }
struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
int length, int channel,
int tag, int sync)
{
struct hpsb_packet *p;
p = hpsb_alloc_packet(length);
if (!p)
return NULL;
p->host = host;
fill_iso_packet(p, length, channel, tag, sync);
p->generation = get_hpsb_generation(host);
return p;
}
/* /*
* FIXME - these functions should probably read from / write to user space to * FIXME - these functions should probably read from / write to user space to
* avoid in kernel buffers for user space callers * avoid in kernel buffers for user space callers
......
...@@ -19,8 +19,6 @@ struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, ...@@ -19,8 +19,6 @@ struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
nodeid_t node, u64 addr, int extcode, nodeid_t node, u64 addr, int extcode,
octlet_t *data, octlet_t arg); octlet_t *data, octlet_t arg);
struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data); 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, struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host,
nodeid_t node, u64 addr, nodeid_t node, u64 addr,
quadlet_t *buffer, size_t length); quadlet_t *buffer, size_t length);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/freezer.h> #include <linux/freezer.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/semaphore.h>
#include "csr.h" #include "csr.h"
#include "highlevel.h" #include "highlevel.h"
...@@ -145,8 +146,6 @@ static struct csr1212_bus_ops nodemgr_csr_ops = { ...@@ -145,8 +146,6 @@ static struct csr1212_bus_ops nodemgr_csr_ops = {
* but now we are much simpler because of the LDM. * but now we are much simpler because of the LDM.
*/ */
static DEFINE_MUTEX(nodemgr_serialize);
struct host_info { struct host_info {
struct hpsb_host *host; struct hpsb_host *host;
struct list_head list; struct list_head list;
...@@ -154,7 +153,7 @@ struct host_info { ...@@ -154,7 +153,7 @@ struct host_info {
}; };
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp, static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size); char *buffer, int buffer_size);
static void nodemgr_resume_ne(struct node_entry *ne); static void nodemgr_resume_ne(struct node_entry *ne);
static void nodemgr_remove_ne(struct node_entry *ne); static void nodemgr_remove_ne(struct node_entry *ne);
...@@ -165,37 +164,38 @@ struct bus_type ieee1394_bus_type = { ...@@ -165,37 +164,38 @@ struct bus_type ieee1394_bus_type = {
.match = nodemgr_bus_match, .match = nodemgr_bus_match,
}; };
static void host_cls_release(struct class_device *class_dev) static void host_cls_release(struct device *dev)
{ {
put_device(&container_of((class_dev), struct hpsb_host, class_dev)->device); put_device(&container_of((dev), struct hpsb_host, host_dev)->device);
} }
struct class hpsb_host_class = { struct class hpsb_host_class = {
.name = "ieee1394_host", .name = "ieee1394_host",
.release = host_cls_release, .dev_release = host_cls_release,
}; };
static void ne_cls_release(struct class_device *class_dev) static void ne_cls_release(struct device *dev)
{ {
put_device(&container_of((class_dev), struct node_entry, class_dev)->device); put_device(&container_of((dev), struct node_entry, node_dev)->device);
} }
static struct class nodemgr_ne_class = { static struct class nodemgr_ne_class = {
.name = "ieee1394_node", .name = "ieee1394_node",
.release = ne_cls_release, .dev_release = ne_cls_release,
}; };
static void ud_cls_release(struct class_device *class_dev) static void ud_cls_release(struct device *dev)
{ {
put_device(&container_of((class_dev), struct unit_directory, class_dev)->device); put_device(&container_of((dev), struct unit_directory, unit_dev)->device);
} }
/* The name here is only so that unit directory hotplug works with old /* The name here is only so that unit directory hotplug works with old
* style hotplug, which only ever did unit directories anyway. */ * style hotplug, which only ever did unit directories anyway.
*/
static struct class nodemgr_ud_class = { static struct class nodemgr_ud_class = {
.name = "ieee1394", .name = "ieee1394",
.release = ud_cls_release, .dev_release = ud_cls_release,
.uevent = nodemgr_uevent, .dev_uevent = nodemgr_uevent,
}; };
static struct hpsb_highlevel nodemgr_highlevel; static struct hpsb_highlevel nodemgr_highlevel;
...@@ -730,11 +730,11 @@ static DEFINE_MUTEX(nodemgr_serialize_remove_uds); ...@@ -730,11 +730,11 @@ static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
static void nodemgr_remove_uds(struct node_entry *ne) static void nodemgr_remove_uds(struct node_entry *ne)
{ {
struct class_device *cdev; struct device *dev;
struct unit_directory *tmp, *ud; struct unit_directory *tmp, *ud;
/* Iteration over nodemgr_ud_class.children has to be protected by /* Iteration over nodemgr_ud_class.devices has to be protected by
* nodemgr_ud_class.sem, but class_device_unregister() will eventually * nodemgr_ud_class.sem, but device_unregister() will eventually
* take nodemgr_ud_class.sem too. Therefore pick out one ud at a time, * take nodemgr_ud_class.sem too. Therefore pick out one ud at a time,
* release the semaphore, and then unregister the ud. Since this code * release the semaphore, and then unregister the ud. Since this code
* may be called from other contexts besides the knodemgrds, protect the * may be called from other contexts besides the knodemgrds, protect the
...@@ -744,9 +744,9 @@ static void nodemgr_remove_uds(struct node_entry *ne) ...@@ -744,9 +744,9 @@ static void nodemgr_remove_uds(struct node_entry *ne)
for (;;) { for (;;) {
ud = NULL; ud = NULL;
down(&nodemgr_ud_class.sem); down(&nodemgr_ud_class.sem);
list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
tmp = container_of(cdev, struct unit_directory, tmp = container_of(dev, struct unit_directory,
class_dev); unit_dev);
if (tmp->ne == ne) { if (tmp->ne == ne) {
ud = tmp; ud = tmp;
break; break;
...@@ -755,7 +755,7 @@ static void nodemgr_remove_uds(struct node_entry *ne) ...@@ -755,7 +755,7 @@ static void nodemgr_remove_uds(struct node_entry *ne)
up(&nodemgr_ud_class.sem); up(&nodemgr_ud_class.sem);
if (ud == NULL) if (ud == NULL)
break; break;
class_device_unregister(&ud->class_dev); device_unregister(&ud->unit_dev);
device_unregister(&ud->device); device_unregister(&ud->device);
} }
mutex_unlock(&nodemgr_serialize_remove_uds); mutex_unlock(&nodemgr_serialize_remove_uds);
...@@ -772,10 +772,9 @@ static void nodemgr_remove_ne(struct node_entry *ne) ...@@ -772,10 +772,9 @@ static void nodemgr_remove_ne(struct node_entry *ne)
HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
nodemgr_remove_uds(ne); nodemgr_remove_uds(ne);
class_device_unregister(&ne->class_dev); device_unregister(&ne->node_dev);
device_unregister(dev); device_unregister(dev);
put_device(dev); put_device(dev);
...@@ -783,7 +782,9 @@ static void nodemgr_remove_ne(struct node_entry *ne) ...@@ -783,7 +782,9 @@ static void nodemgr_remove_ne(struct node_entry *ne)
static int __nodemgr_remove_host_dev(struct device *dev, void *data) static int __nodemgr_remove_host_dev(struct device *dev, void *data)
{ {
nodemgr_remove_ne(container_of(dev, struct node_entry, device)); if (dev->bus == &ieee1394_bus_type)
nodemgr_remove_ne(container_of(dev, struct node_entry,
device));
return 0; return 0;
} }
...@@ -850,14 +851,14 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr ...@@ -850,14 +851,14 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx", snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx",
(unsigned long long)(ne->guid)); (unsigned long long)(ne->guid));
ne->class_dev.dev = &ne->device; ne->node_dev.parent = &ne->device;
ne->class_dev.class = &nodemgr_ne_class; ne->node_dev.class = &nodemgr_ne_class;
snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx", snprintf(ne->node_dev.bus_id, BUS_ID_SIZE, "%016Lx",
(unsigned long long)(ne->guid)); (unsigned long long)(ne->guid));
if (device_register(&ne->device)) if (device_register(&ne->device))
goto fail_devreg; goto fail_devreg;
if (class_device_register(&ne->class_dev)) if (device_register(&ne->node_dev))
goto fail_classdevreg; goto fail_classdevreg;
get_device(&ne->device); get_device(&ne->device);
...@@ -885,12 +886,12 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr ...@@ -885,12 +886,12 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
static struct node_entry *find_entry_by_guid(u64 guid) static struct node_entry *find_entry_by_guid(u64 guid)
{ {
struct class_device *cdev; struct device *dev;
struct node_entry *ne, *ret_ne = NULL; struct node_entry *ne, *ret_ne = NULL;
down(&nodemgr_ne_class.sem); down(&nodemgr_ne_class.sem);
list_for_each_entry(cdev, &nodemgr_ne_class.children, node) { list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
ne = container_of(cdev, struct node_entry, class_dev); ne = container_of(dev, struct node_entry, node_dev);
if (ne->guid == guid) { if (ne->guid == guid) {
ret_ne = ne; ret_ne = ne;
...@@ -906,12 +907,12 @@ static struct node_entry *find_entry_by_guid(u64 guid) ...@@ -906,12 +907,12 @@ static struct node_entry *find_entry_by_guid(u64 guid)
static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
nodeid_t nodeid) nodeid_t nodeid)
{ {
struct class_device *cdev; struct device *dev;
struct node_entry *ne, *ret_ne = NULL; struct node_entry *ne, *ret_ne = NULL;
down(&nodemgr_ne_class.sem); down(&nodemgr_ne_class.sem);
list_for_each_entry(cdev, &nodemgr_ne_class.children, node) { list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
ne = container_of(cdev, struct node_entry, class_dev); ne = container_of(dev, struct node_entry, node_dev);
if (ne->host == host && ne->nodeid == nodeid) { if (ne->host == host && ne->nodeid == nodeid) {
ret_ne = ne; ret_ne = ne;
...@@ -935,14 +936,14 @@ static void nodemgr_register_device(struct node_entry *ne, ...@@ -935,14 +936,14 @@ static void nodemgr_register_device(struct node_entry *ne,
snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u", snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
ne->device.bus_id, ud->id); ne->device.bus_id, ud->id);
ud->class_dev.dev = &ud->device; ud->unit_dev.parent = &ud->device;
ud->class_dev.class = &nodemgr_ud_class; ud->unit_dev.class = &nodemgr_ud_class;
snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u", snprintf(ud->unit_dev.bus_id, BUS_ID_SIZE, "%s-%u",
ne->device.bus_id, ud->id); ne->device.bus_id, ud->id);
if (device_register(&ud->device)) if (device_register(&ud->device))
goto fail_devreg; goto fail_devreg;
if (class_device_register(&ud->class_dev)) if (device_register(&ud->unit_dev))
goto fail_classdevreg; goto fail_classdevreg;
get_device(&ud->device); get_device(&ud->device);
...@@ -1159,7 +1160,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent ...@@ -1159,7 +1160,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp, static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size) char *buffer, int buffer_size)
{ {
struct unit_directory *ud; struct unit_directory *ud;
...@@ -1169,10 +1170,10 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp, ...@@ -1169,10 +1170,10 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
/* ieee1394:venNmoNspNverN */ /* ieee1394:venNmoNspNverN */
char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1]; char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
if (!cdev) if (!dev)
return -ENODEV; return -ENODEV;
ud = container_of(cdev, struct unit_directory, class_dev); ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne->in_limbo || ud->ignore_driver) if (ud->ne->in_limbo || ud->ignore_driver)
return -ENODEV; return -ENODEV;
...@@ -1207,7 +1208,7 @@ do { \ ...@@ -1207,7 +1208,7 @@ do { \
#else #else
static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp, static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size) char *buffer, int buffer_size)
{ {
return -ENODEV; return -ENODEV;
...@@ -1378,8 +1379,10 @@ static void nodemgr_node_scan(struct host_info *hi, int generation) ...@@ -1378,8 +1379,10 @@ static void nodemgr_node_scan(struct host_info *hi, int generation)
static void nodemgr_suspend_ne(struct node_entry *ne) static void nodemgr_suspend_ne(struct node_entry *ne)
{ {
struct class_device *cdev; struct device *dev;
struct unit_directory *ud; struct unit_directory *ud;
struct device_driver *drv;
int error;
HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
...@@ -1388,15 +1391,24 @@ static void nodemgr_suspend_ne(struct node_entry *ne) ...@@ -1388,15 +1391,24 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo)); WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
down(&nodemgr_ud_class.sem); down(&nodemgr_ud_class.sem);
list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
ud = container_of(cdev, struct unit_directory, class_dev); ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne != ne) if (ud->ne != ne)
continue; continue;
if (ud->device.driver && drv = get_driver(ud->device.driver);
(!ud->device.driver->suspend || if (!drv)
ud->device.driver->suspend(&ud->device, PMSG_SUSPEND))) continue;
error = 1; /* release if suspend is not implemented */
if (drv->suspend) {
down(&ud->device.sem);
error = drv->suspend(&ud->device, PMSG_SUSPEND);
up(&ud->device.sem);
}
if (error)
device_release_driver(&ud->device); device_release_driver(&ud->device);
put_driver(drv);
} }
up(&nodemgr_ud_class.sem); up(&nodemgr_ud_class.sem);
} }
...@@ -1404,20 +1416,29 @@ static void nodemgr_suspend_ne(struct node_entry *ne) ...@@ -1404,20 +1416,29 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
static void nodemgr_resume_ne(struct node_entry *ne) static void nodemgr_resume_ne(struct node_entry *ne)
{ {
struct class_device *cdev; struct device *dev;
struct unit_directory *ud; struct unit_directory *ud;
struct device_driver *drv;
ne->in_limbo = 0; ne->in_limbo = 0;
device_remove_file(&ne->device, &dev_attr_ne_in_limbo); device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
down(&nodemgr_ud_class.sem); down(&nodemgr_ud_class.sem);
list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
ud = container_of(cdev, struct unit_directory, class_dev); ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne != ne) if (ud->ne != ne)
continue; continue;
if (ud->device.driver && ud->device.driver->resume) drv = get_driver(ud->device.driver);
ud->device.driver->resume(&ud->device); if (!drv)
continue;
if (drv->resume) {
down(&ud->device.sem);
drv->resume(&ud->device);
up(&ud->device.sem);
}
put_driver(drv);
} }
up(&nodemgr_ud_class.sem); up(&nodemgr_ud_class.sem);
...@@ -1428,23 +1449,32 @@ static void nodemgr_resume_ne(struct node_entry *ne) ...@@ -1428,23 +1449,32 @@ static void nodemgr_resume_ne(struct node_entry *ne)
static void nodemgr_update_pdrv(struct node_entry *ne) static void nodemgr_update_pdrv(struct node_entry *ne)
{ {
struct device *dev;
struct unit_directory *ud; struct unit_directory *ud;
struct device_driver *drv;
struct hpsb_protocol_driver *pdrv; struct hpsb_protocol_driver *pdrv;
struct class_device *cdev; int error;
down(&nodemgr_ud_class.sem); down(&nodemgr_ud_class.sem);
list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
ud = container_of(cdev, struct unit_directory, class_dev); ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne != ne) if (ud->ne != ne)
continue; continue;
if (ud->device.driver) { drv = get_driver(ud->device.driver);
pdrv = container_of(ud->device.driver, if (!drv)
struct hpsb_protocol_driver, continue;
driver);
if (pdrv->update && pdrv->update(ud)) error = 0;
device_release_driver(&ud->device); pdrv = container_of(drv, struct hpsb_protocol_driver, driver);
if (pdrv->update) {
down(&ud->device.sem);
error = pdrv->update(ud);
up(&ud->device.sem);
} }
if (error)
device_release_driver(&ud->device);
put_driver(drv);
} }
up(&nodemgr_ud_class.sem); up(&nodemgr_ud_class.sem);
} }
...@@ -1509,7 +1539,7 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge ...@@ -1509,7 +1539,7 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
static void nodemgr_node_probe(struct host_info *hi, int generation) static void nodemgr_node_probe(struct host_info *hi, int generation)
{ {
struct hpsb_host *host = hi->host; struct hpsb_host *host = hi->host;
struct class_device *cdev; struct device *dev;
struct node_entry *ne; struct node_entry *ne;
/* Do some processing of the nodes we've probed. This pulls them /* Do some processing of the nodes we've probed. This pulls them
...@@ -1522,13 +1552,13 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) ...@@ -1522,13 +1552,13 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
* improvement...) */ * improvement...) */
down(&nodemgr_ne_class.sem); down(&nodemgr_ne_class.sem);
list_for_each_entry(cdev, &nodemgr_ne_class.children, node) { list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
ne = container_of(cdev, struct node_entry, class_dev); ne = container_of(dev, struct node_entry, node_dev);
if (!ne->needs_probe) if (!ne->needs_probe)
nodemgr_probe_ne(hi, ne, generation); nodemgr_probe_ne(hi, ne, generation);
} }
list_for_each_entry(cdev, &nodemgr_ne_class.children, node) { list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
ne = container_of(cdev, struct node_entry, class_dev); ne = container_of(dev, struct node_entry, node_dev);
if (ne->needs_probe) if (ne->needs_probe)
nodemgr_probe_ne(hi, ne, generation); nodemgr_probe_ne(hi, ne, generation);
} }
...@@ -1686,18 +1716,12 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1686,18 +1716,12 @@ static int nodemgr_host_thread(void *__hi)
if (kthread_should_stop()) if (kthread_should_stop())
goto exit; goto exit;
if (mutex_lock_interruptible(&nodemgr_serialize)) {
if (try_to_freeze())
continue;
goto exit;
}
/* Pause for 1/4 second in 1/16 second intervals, /* Pause for 1/4 second in 1/16 second intervals,
* to make sure things settle down. */ * to make sure things settle down. */
g = get_hpsb_generation(host); g = get_hpsb_generation(host);
for (i = 0; i < 4 ; i++) { for (i = 0; i < 4 ; i++) {
if (msleep_interruptible(63) || kthread_should_stop()) if (msleep_interruptible(63) || kthread_should_stop())
goto unlock_exit; goto exit;
/* Now get the generation in which the node ID's we collect /* Now get the generation in which the node ID's we collect
* are valid. During the bus scan we will use this generation * are valid. During the bus scan we will use this generation
...@@ -1715,7 +1739,6 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1715,7 +1739,6 @@ static int nodemgr_host_thread(void *__hi)
if (!nodemgr_check_irm_capability(host, reset_cycles) || if (!nodemgr_check_irm_capability(host, reset_cycles) ||
!nodemgr_do_irm_duties(host, reset_cycles)) { !nodemgr_do_irm_duties(host, reset_cycles)) {
reset_cycles++; reset_cycles++;
mutex_unlock(&nodemgr_serialize);
continue; continue;
} }
reset_cycles = 0; reset_cycles = 0;
...@@ -1732,11 +1755,7 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1732,11 +1755,7 @@ static int nodemgr_host_thread(void *__hi)
/* Update some of our sysfs symlinks */ /* Update some of our sysfs symlinks */
nodemgr_update_host_dev_links(host); nodemgr_update_host_dev_links(host);
mutex_unlock(&nodemgr_serialize);
} }
unlock_exit:
mutex_unlock(&nodemgr_serialize);
exit: exit:
HPSB_VERBOSE("NodeMgr: Exiting thread"); HPSB_VERBOSE("NodeMgr: Exiting thread");
return 0; return 0;
...@@ -1756,13 +1775,13 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1756,13 +1775,13 @@ static int nodemgr_host_thread(void *__hi)
*/ */
int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *)) int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
{ {
struct class_device *cdev; struct device *dev;
struct hpsb_host *host; struct hpsb_host *host;
int error = 0; int error = 0;
down(&hpsb_host_class.sem); down(&hpsb_host_class.sem);
list_for_each_entry(cdev, &hpsb_host_class.children, node) { list_for_each_entry(dev, &hpsb_host_class.devices, node) {
host = container_of(cdev, struct hpsb_host, class_dev); host = container_of(dev, struct hpsb_host, host_dev);
if ((error = cb(host, data))) if ((error = cb(host, data)))
break; break;
......
...@@ -84,7 +84,7 @@ struct unit_directory { ...@@ -84,7 +84,7 @@ struct unit_directory {
int length; /* Number of quadlets */ int length; /* Number of quadlets */
struct device device; struct device device;
struct class_device class_dev; struct device unit_dev;
struct csr1212_keyval *ud_kv; struct csr1212_keyval *ud_kv;
u32 lun; /* logical unit number immediate value */ u32 lun; /* logical unit number immediate value */
...@@ -107,7 +107,7 @@ struct node_entry { ...@@ -107,7 +107,7 @@ struct node_entry {
u32 capabilities; u32 capabilities;
struct device device; struct device device;
struct class_device class_dev; struct device node_dev;
/* Means this node is not attached anymore */ /* Means this node is not attached anymore */
int in_limbo; int in_limbo;
......
...@@ -138,19 +138,6 @@ printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host-> ...@@ -138,19 +138,6 @@ printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->
#define DBGMSG(fmt, args...) do {} while (0) #define DBGMSG(fmt, args...) do {} while (0)
#endif #endif
#ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG
#define OHCI_DMA_ALLOC(fmt, args...) \
HPSB_ERR("%s(%s)alloc(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
++global_outstanding_dmas, ## args)
#define OHCI_DMA_FREE(fmt, args...) \
HPSB_ERR("%s(%s)free(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
--global_outstanding_dmas, ## args)
static int global_outstanding_dmas = 0;
#else
#define OHCI_DMA_ALLOC(fmt, args...) do {} while (0)
#define OHCI_DMA_FREE(fmt, args...) do {} while (0)
#endif
/* print general (card independent) information */ /* print general (card independent) information */
#define PRINT_G(level, fmt, args...) \ #define PRINT_G(level, fmt, args...) \
printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args) printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
...@@ -170,7 +157,6 @@ static void dma_trm_reset(struct dma_trm_ctx *d); ...@@ -170,7 +157,6 @@ static void dma_trm_reset(struct dma_trm_ctx *d);
static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
enum context_type type, int ctx, int num_desc, enum context_type type, int ctx, int num_desc,
int buf_size, int split_buf_size, int context_base); int buf_size, int split_buf_size, int context_base);
static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d);
static void free_dma_rcv_ctx(struct dma_rcv_ctx *d); static void free_dma_rcv_ctx(struct dma_rcv_ctx *d);
static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
...@@ -533,9 +519,6 @@ static void ohci_initialize(struct ti_ohci *ohci) ...@@ -533,9 +519,6 @@ static void ohci_initialize(struct ti_ohci *ohci)
initialize_dma_trm_ctx(&ohci->at_req_context); initialize_dma_trm_ctx(&ohci->at_req_context);
initialize_dma_trm_ctx(&ohci->at_resp_context); initialize_dma_trm_ctx(&ohci->at_resp_context);
/* Initialize IR Legacy DMA channel mask */
ohci->ir_legacy_channels = 0;
/* Accept AR requests from all nodes */ /* Accept AR requests from all nodes */
reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000); reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
...@@ -733,7 +716,6 @@ static void insert_packet(struct ti_ohci *ohci, ...@@ -733,7 +716,6 @@ static void insert_packet(struct ti_ohci *ohci,
pci_map_single(ohci->dev, packet->data, pci_map_single(ohci->dev, packet->data,
packet->data_size, packet->data_size,
PCI_DMA_TODEVICE)); PCI_DMA_TODEVICE));
OHCI_DMA_ALLOC("single, block transmit packet");
d->prg_cpu[idx]->end.branchAddress = 0; d->prg_cpu[idx]->end.branchAddress = 0;
d->prg_cpu[idx]->end.status = 0; d->prg_cpu[idx]->end.status = 0;
...@@ -783,7 +765,6 @@ static void insert_packet(struct ti_ohci *ohci, ...@@ -783,7 +765,6 @@ static void insert_packet(struct ti_ohci *ohci,
d->prg_cpu[idx]->end.address = cpu_to_le32( d->prg_cpu[idx]->end.address = cpu_to_le32(
pci_map_single(ohci->dev, packet->data, pci_map_single(ohci->dev, packet->data,
packet->data_size, PCI_DMA_TODEVICE)); packet->data_size, PCI_DMA_TODEVICE));
OHCI_DMA_ALLOC("single, iso transmit packet");
d->prg_cpu[idx]->end.branchAddress = 0; d->prg_cpu[idx]->end.branchAddress = 0;
d->prg_cpu[idx]->end.status = 0; d->prg_cpu[idx]->end.status = 0;
...@@ -884,36 +865,9 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet) ...@@ -884,36 +865,9 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
return -EOVERFLOW; return -EOVERFLOW;
} }
/* Decide whether we have an iso, a request, or a response packet */
if (packet->type == hpsb_raw) if (packet->type == hpsb_raw)
d = &ohci->at_req_context; d = &ohci->at_req_context;
else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) { else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
/* The legacy IT DMA context is initialized on first
* use. However, the alloc cannot be run from
* interrupt context, so we bail out if that is the
* case. I don't see anyone sending ISO packets from
* interrupt context anyway... */
if (ohci->it_legacy_context.ohci == NULL) {
if (in_interrupt()) {
PRINT(KERN_ERR,
"legacy IT context cannot be initialized during interrupt");
return -EINVAL;
}
if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context,
DMA_CTX_ISO, 0, IT_NUM_DESC,
OHCI1394_IsoXmitContextBase) < 0) {
PRINT(KERN_ERR,
"error initializing legacy IT context");
return -ENOMEM;
}
initialize_dma_trm_ctx(&ohci->it_legacy_context);
}
d = &ohci->it_legacy_context;
} else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
d = &ohci->at_resp_context; d = &ohci->at_resp_context;
else else
d = &ohci->at_req_context; d = &ohci->at_req_context;
...@@ -932,9 +886,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet) ...@@ -932,9 +886,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
{ {
struct ti_ohci *ohci = host->hostdata; struct ti_ohci *ohci = host->hostdata;
int retval = 0; int retval = 0, phy_reg;
unsigned long flags;
int phy_reg;
switch (cmd) { switch (cmd) {
case RESET_BUS: case RESET_BUS:
...@@ -1027,117 +979,6 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) ...@@ -1027,117 +979,6 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
dma_trm_reset(&ohci->at_resp_context); dma_trm_reset(&ohci->at_resp_context);
break; break;
case ISO_LISTEN_CHANNEL:
{
u64 mask;
struct dma_rcv_ctx *d = &ohci->ir_legacy_context;
int ir_legacy_active;
if (arg<0 || arg>63) {
PRINT(KERN_ERR,
"%s: IS0 listen channel %d is out of range",
__FUNCTION__, arg);
return -EFAULT;
}
mask = (u64)0x1<<arg;
spin_lock_irqsave(&ohci->IR_channel_lock, flags);
if (ohci->ISO_channel_usage & mask) {
PRINT(KERN_ERR,
"%s: IS0 listen channel %d is already used",
__FUNCTION__, arg);
spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
return -EFAULT;
}
ir_legacy_active = ohci->ir_legacy_channels;
ohci->ISO_channel_usage |= mask;
ohci->ir_legacy_channels |= mask;
spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
if (!ir_legacy_active) {
if (ohci1394_register_iso_tasklet(ohci,
&ohci->ir_legacy_tasklet) < 0) {
PRINT(KERN_ERR, "No IR DMA context available");
return -EBUSY;
}
/* the IR context can be assigned to any DMA context
* by ohci1394_register_iso_tasklet */
d->ctx = ohci->ir_legacy_tasklet.context;
d->ctrlSet = OHCI1394_IsoRcvContextControlSet +
32*d->ctx;
d->ctrlClear = OHCI1394_IsoRcvContextControlClear +
32*d->ctx;
d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx;
d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx;
initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
if (printk_ratelimit())
DBGMSG("IR legacy activated");
}
spin_lock_irqsave(&ohci->IR_channel_lock, flags);
if (arg>31)
reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet,
1<<(arg-32));
else
reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet,
1<<arg);
spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
DBGMSG("Listening enabled on channel %d", arg);
break;
}
case ISO_UNLISTEN_CHANNEL:
{
u64 mask;
if (arg<0 || arg>63) {
PRINT(KERN_ERR,
"%s: IS0 unlisten channel %d is out of range",
__FUNCTION__, arg);
return -EFAULT;
}
mask = (u64)0x1<<arg;
spin_lock_irqsave(&ohci->IR_channel_lock, flags);
if (!(ohci->ISO_channel_usage & mask)) {
PRINT(KERN_ERR,
"%s: IS0 unlisten channel %d is not used",
__FUNCTION__, arg);
spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
return -EFAULT;
}
ohci->ISO_channel_usage &= ~mask;
ohci->ir_legacy_channels &= ~mask;
if (arg>31)
reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear,
1<<(arg-32));
else
reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear,
1<<arg);
spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
DBGMSG("Listening disabled on channel %d", arg);
if (ohci->ir_legacy_channels == 0) {
stop_dma_rcv_ctx(&ohci->ir_legacy_context);
DBGMSG("ISO legacy receive context stopped");
}
break;
}
default: default:
PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet", PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet",
cmd); cmd);
...@@ -2869,12 +2710,10 @@ static void dma_trm_tasklet (unsigned long data) ...@@ -2869,12 +2710,10 @@ static void dma_trm_tasklet (unsigned long data)
list_del_init(&packet->driver_list); list_del_init(&packet->driver_list);
hpsb_packet_sent(ohci->host, packet, ack); hpsb_packet_sent(ohci->host, packet, ack);
if (datasize) { if (datasize)
pci_unmap_single(ohci->dev, pci_unmap_single(ohci->dev,
cpu_to_le32(d->prg_cpu[d->sent_ind]->end.address), cpu_to_le32(d->prg_cpu[d->sent_ind]->end.address),
datasize, PCI_DMA_TODEVICE); datasize, PCI_DMA_TODEVICE);
OHCI_DMA_FREE("single Xmit data packet");
}
d->sent_ind = (d->sent_ind+1)%d->num_desc; d->sent_ind = (d->sent_ind+1)%d->num_desc;
d->free_prgs++; d->free_prgs++;
...@@ -2885,22 +2724,6 @@ static void dma_trm_tasklet (unsigned long data) ...@@ -2885,22 +2724,6 @@ static void dma_trm_tasklet (unsigned long data)
spin_unlock_irqrestore(&d->lock, flags); spin_unlock_irqrestore(&d->lock, flags);
} }
static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d)
{
if (d->ctrlClear) {
ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
if (d->type == DMA_CTX_ISO) {
/* disable interrupts */
reg_write(d->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << d->ctx);
ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_legacy_tasklet);
} else {
tasklet_kill(&d->task);
}
}
}
static void free_dma_rcv_ctx(struct dma_rcv_ctx *d) static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
{ {
int i; int i;
...@@ -2913,23 +2736,19 @@ static void free_dma_rcv_ctx(struct dma_rcv_ctx *d) ...@@ -2913,23 +2736,19 @@ static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
if (d->buf_cpu) { if (d->buf_cpu) {
for (i=0; i<d->num_desc; i++) for (i=0; i<d->num_desc; i++)
if (d->buf_cpu[i] && d->buf_bus[i]) { if (d->buf_cpu[i] && d->buf_bus[i])
pci_free_consistent( pci_free_consistent(
ohci->dev, d->buf_size, ohci->dev, d->buf_size,
d->buf_cpu[i], d->buf_bus[i]); d->buf_cpu[i], d->buf_bus[i]);
OHCI_DMA_FREE("consistent dma_rcv buf[%d]", i);
}
kfree(d->buf_cpu); kfree(d->buf_cpu);
kfree(d->buf_bus); kfree(d->buf_bus);
} }
if (d->prg_cpu) { if (d->prg_cpu) {
for (i=0; i<d->num_desc; i++) for (i=0; i<d->num_desc; i++)
if (d->prg_cpu[i] && d->prg_bus[i]) { if (d->prg_cpu[i] && d->prg_bus[i])
pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]); pci_pool_free(d->prg_pool, d->prg_cpu[i],
OHCI_DMA_FREE("consistent dma_rcv prg[%d]", i); d->prg_bus[i]);
}
pci_pool_destroy(d->prg_pool); pci_pool_destroy(d->prg_pool);
OHCI_DMA_FREE("dma_rcv prg pool");
kfree(d->prg_cpu); kfree(d->prg_cpu);
kfree(d->prg_bus); kfree(d->prg_bus);
} }
...@@ -2998,13 +2817,10 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, ...@@ -2998,13 +2817,10 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
} }
num_allocs++; num_allocs++;
OHCI_DMA_ALLOC("dma_rcv prg pool");
for (i=0; i<d->num_desc; i++) { for (i=0; i<d->num_desc; i++) {
d->buf_cpu[i] = pci_alloc_consistent(ohci->dev, d->buf_cpu[i] = pci_alloc_consistent(ohci->dev,
d->buf_size, d->buf_size,
d->buf_bus+i); d->buf_bus+i);
OHCI_DMA_ALLOC("consistent dma_rcv buf[%d]", i);
if (d->buf_cpu[i] != NULL) { if (d->buf_cpu[i] != NULL) {
memset(d->buf_cpu[i], 0, d->buf_size); memset(d->buf_cpu[i], 0, d->buf_size);
...@@ -3016,7 +2832,6 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, ...@@ -3016,7 +2832,6 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
} }
d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i); d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
OHCI_DMA_ALLOC("pool dma_rcv prg[%d]", i);
if (d->prg_cpu[i] != NULL) { if (d->prg_cpu[i] != NULL) {
memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd)); memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
...@@ -3030,18 +2845,11 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, ...@@ -3030,18 +2845,11 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
spin_lock_init(&d->lock); spin_lock_init(&d->lock);
if (type == DMA_CTX_ISO) {
ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet,
OHCI_ISO_MULTICHANNEL_RECEIVE,
dma_rcv_tasklet, (unsigned long) d);
} else {
d->ctrlSet = context_base + OHCI1394_ContextControlSet; d->ctrlSet = context_base + OHCI1394_ContextControlSet;
d->ctrlClear = context_base + OHCI1394_ContextControlClear; d->ctrlClear = context_base + OHCI1394_ContextControlClear;
d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d); tasklet_init(&d->task, dma_rcv_tasklet, (unsigned long) d);
}
return 0; return 0;
} }
...@@ -3057,12 +2865,10 @@ static void free_dma_trm_ctx(struct dma_trm_ctx *d) ...@@ -3057,12 +2865,10 @@ static void free_dma_trm_ctx(struct dma_trm_ctx *d)
if (d->prg_cpu) { if (d->prg_cpu) {
for (i=0; i<d->num_desc; i++) for (i=0; i<d->num_desc; i++)
if (d->prg_cpu[i] && d->prg_bus[i]) { if (d->prg_cpu[i] && d->prg_bus[i])
pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]); pci_pool_free(d->prg_pool, d->prg_cpu[i],
OHCI_DMA_FREE("pool dma_trm prg[%d]", i); d->prg_bus[i]);
}
pci_pool_destroy(d->prg_pool); pci_pool_destroy(d->prg_pool);
OHCI_DMA_FREE("dma_trm prg pool");
kfree(d->prg_cpu); kfree(d->prg_cpu);
kfree(d->prg_bus); kfree(d->prg_bus);
} }
...@@ -3108,11 +2914,8 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, ...@@ -3108,11 +2914,8 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
} }
num_allocs++; num_allocs++;
OHCI_DMA_ALLOC("dma_rcv prg pool");
for (i = 0; i < d->num_desc; i++) { for (i = 0; i < d->num_desc; i++) {
d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i); d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
OHCI_DMA_ALLOC("pool dma_trm prg[%d]", i);
if (d->prg_cpu[i] != NULL) { if (d->prg_cpu[i] != NULL) {
memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg)); memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg));
...@@ -3127,28 +2930,10 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, ...@@ -3127,28 +2930,10 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
spin_lock_init(&d->lock); spin_lock_init(&d->lock);
/* initialize tasklet */ /* initialize tasklet */
if (type == DMA_CTX_ISO) {
ohci1394_init_iso_tasklet(&ohci->it_legacy_tasklet, OHCI_ISO_TRANSMIT,
dma_trm_tasklet, (unsigned long) d);
if (ohci1394_register_iso_tasklet(ohci,
&ohci->it_legacy_tasklet) < 0) {
PRINT(KERN_ERR, "No IT DMA context available");
free_dma_trm_ctx(d);
return -EBUSY;
}
/* IT can be assigned to any context by register_iso_tasklet */
d->ctx = ohci->it_legacy_tasklet.context;
d->ctrlSet = OHCI1394_IsoXmitContextControlSet + 16 * d->ctx;
d->ctrlClear = OHCI1394_IsoXmitContextControlClear + 16 * d->ctx;
d->cmdPtr = OHCI1394_IsoXmitCommandPtr + 16 * d->ctx;
} else {
d->ctrlSet = context_base + OHCI1394_ContextControlSet; d->ctrlSet = context_base + OHCI1394_ContextControlSet;
d->ctrlClear = context_base + OHCI1394_ContextControlClear; d->ctrlClear = context_base + OHCI1394_ContextControlClear;
d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
tasklet_init (&d->task, dma_trm_tasklet, (unsigned long)d); tasklet_init(&d->task, dma_trm_tasklet, (unsigned long)d);
}
return 0; return 0;
} }
...@@ -3294,7 +3079,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev, ...@@ -3294,7 +3079,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->csr_config_rom_cpu = ohci->csr_config_rom_cpu =
pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN, pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
&ohci->csr_config_rom_bus); &ohci->csr_config_rom_bus);
OHCI_DMA_ALLOC("consistent csr_config_rom");
if (ohci->csr_config_rom_cpu == NULL) if (ohci->csr_config_rom_cpu == NULL)
FAIL(-ENOMEM, "Failed to allocate buffer config rom"); FAIL(-ENOMEM, "Failed to allocate buffer config rom");
ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER; ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER;
...@@ -3303,8 +3087,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev, ...@@ -3303,8 +3087,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->selfid_buf_cpu = ohci->selfid_buf_cpu =
pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
&ohci->selfid_buf_bus); &ohci->selfid_buf_bus);
OHCI_DMA_ALLOC("consistent selfid_buf");
if (ohci->selfid_buf_cpu == NULL) if (ohci->selfid_buf_cpu == NULL)
FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets"); FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets");
ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER; ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
...@@ -3377,20 +3159,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev, ...@@ -3377,20 +3159,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->ISO_channel_usage = 0; ohci->ISO_channel_usage = 0;
spin_lock_init(&ohci->IR_channel_lock); spin_lock_init(&ohci->IR_channel_lock);
/* Allocate the IR DMA context right here so we don't have
* to do it in interrupt path - note that this doesn't
* waste much memory and avoids the jugglery required to
* allocate it in IRQ path. */
if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
DMA_CTX_ISO, 0, IR_NUM_DESC,
IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
OHCI1394_IsoRcvContextBase) < 0) {
FAIL(-ENOMEM, "Cannot allocate IR Legacy DMA context");
}
/* We hopefully don't have to pre-allocate IT DMA like we did
* for IR DMA above. Allocate it on-demand and mark inactive. */
ohci->it_legacy_context.ohci = NULL;
spin_lock_init(&ohci->event_lock); spin_lock_init(&ohci->event_lock);
/* /*
...@@ -3483,20 +3251,16 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) ...@@ -3483,20 +3251,16 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
free_dma_rcv_ctx(&ohci->ar_resp_context); free_dma_rcv_ctx(&ohci->ar_resp_context);
free_dma_trm_ctx(&ohci->at_req_context); free_dma_trm_ctx(&ohci->at_req_context);
free_dma_trm_ctx(&ohci->at_resp_context); free_dma_trm_ctx(&ohci->at_resp_context);
free_dma_rcv_ctx(&ohci->ir_legacy_context);
free_dma_trm_ctx(&ohci->it_legacy_context);
case OHCI_INIT_HAVE_SELFID_BUFFER: case OHCI_INIT_HAVE_SELFID_BUFFER:
pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
ohci->selfid_buf_cpu, ohci->selfid_buf_cpu,
ohci->selfid_buf_bus); ohci->selfid_buf_bus);
OHCI_DMA_FREE("consistent selfid_buf");
case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER: case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER:
pci_free_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN, pci_free_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
ohci->csr_config_rom_cpu, ohci->csr_config_rom_cpu,
ohci->csr_config_rom_bus); ohci->csr_config_rom_bus);
OHCI_DMA_FREE("consistent csr_config_rom");
case OHCI_INIT_HAVE_IOMAPPING: case OHCI_INIT_HAVE_IOMAPPING:
iounmap(ohci->registers); iounmap(ohci->registers);
......
...@@ -190,23 +190,10 @@ struct ti_ohci { ...@@ -190,23 +190,10 @@ struct ti_ohci {
unsigned long ir_multichannel_used; /* ditto */ unsigned long ir_multichannel_used; /* ditto */
spinlock_t IR_channel_lock; spinlock_t IR_channel_lock;
/* iso receive (legacy API) */
u64 ir_legacy_channels; /* note: this differs from ISO_channel_usage;
it only accounts for channels listened to
by the legacy API, so that we can know when
it is safe to free the legacy API context */
struct dma_rcv_ctx ir_legacy_context;
struct ohci1394_iso_tasklet ir_legacy_tasklet;
/* iso transmit */ /* iso transmit */
int nb_iso_xmit_ctx; int nb_iso_xmit_ctx;
unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */ unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */
/* iso transmit (legacy API) */
struct dma_trm_ctx it_legacy_context;
struct ohci1394_iso_tasklet it_legacy_tasklet;
u64 ISO_channel_usage; u64 ISO_channel_usage;
/* IEEE-1394 part follows */ /* IEEE-1394 part follows */
...@@ -221,7 +208,6 @@ struct ti_ohci { ...@@ -221,7 +208,6 @@ struct ti_ohci {
/* Tasklets for iso receive and transmit, used by video1394 /* Tasklets for iso receive and transmit, used by video1394
* and dv1394 */ * and dv1394 */
struct list_head iso_tasklet_list; struct list_head iso_tasklet_list;
spinlock_t iso_tasklet_list_lock; spinlock_t iso_tasklet_list_lock;
......
...@@ -477,7 +477,11 @@ static void send_next(struct ti_lynx *lynx, int what) ...@@ -477,7 +477,11 @@ static void send_next(struct ti_lynx *lynx, int what)
struct lynx_send_data *d; struct lynx_send_data *d;
struct hpsb_packet *packet; struct hpsb_packet *packet;
#if 0 /* has been removed from ieee1394 core */
d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async); d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
#else
d = &lynx->async;
#endif
if (!list_empty(&d->pcl_queue)) { if (!list_empty(&d->pcl_queue)) {
PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo"); PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo");
BUG(); BUG();
...@@ -511,9 +515,11 @@ static void send_next(struct ti_lynx *lynx, int what) ...@@ -511,9 +515,11 @@ static void send_next(struct ti_lynx *lynx, int what)
case hpsb_async: case hpsb_async:
pcl.buffer[0].control |= PCL_CMD_XMT; pcl.buffer[0].control |= PCL_CMD_XMT;
break; break;
#if 0 /* has been removed from ieee1394 core */
case hpsb_iso: case hpsb_iso:
pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE; pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;
break; break;
#endif
case hpsb_raw: case hpsb_raw:
pcl.buffer[0].control |= PCL_CMD_UNFXMT; pcl.buffer[0].control |= PCL_CMD_UNFXMT;
break; break;
...@@ -542,9 +548,11 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet) ...@@ -542,9 +548,11 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
case hpsb_raw: case hpsb_raw:
d = &lynx->async; d = &lynx->async;
break; break;
#if 0 /* has been removed from ieee1394 core */
case hpsb_iso: case hpsb_iso:
d = &lynx->iso_send; d = &lynx->iso_send;
break; break;
#endif
default: default:
PRINT(KERN_ERR, lynx->id, "invalid packet type %d", PRINT(KERN_ERR, lynx->id, "invalid packet type %d",
packet->type); packet->type);
...@@ -797,7 +805,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) ...@@ -797,7 +805,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
} }
break; break;
#if 0 /* has been removed from ieee1394 core */
case ISO_LISTEN_CHANNEL: case ISO_LISTEN_CHANNEL:
spin_lock_irqsave(&lynx->iso_rcv.lock, flags); spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
...@@ -819,7 +827,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) ...@@ -819,7 +827,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags); spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
break; break;
#endif
default: default:
PRINT(KERN_ERR, lynx->id, "unknown devctl command %d", cmd); PRINT(KERN_ERR, lynx->id, "unknown devctl command %d", cmd);
retval = -1; retval = -1;
...@@ -1009,11 +1017,11 @@ static irqreturn_t lynx_irq_handler(int irq, void *dev_id) ...@@ -1009,11 +1017,11 @@ static irqreturn_t lynx_irq_handler(int irq, void *dev_id)
pci_unmap_single(lynx->dev, lynx->iso_send.data_dma, pci_unmap_single(lynx->dev, lynx->iso_send.data_dma,
packet->data_size, PCI_DMA_TODEVICE); packet->data_size, PCI_DMA_TODEVICE);
} }
#if 0 /* has been removed from ieee1394 core */
if (!list_empty(&lynx->iso_send.queue)) { if (!list_empty(&lynx->iso_send.queue)) {
send_next(lynx, hpsb_iso); send_next(lynx, hpsb_iso);
} }
#endif
spin_unlock(&lynx->iso_send.queue_lock); spin_unlock(&lynx->iso_send.queue_lock);
if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) { if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
......
...@@ -36,11 +36,6 @@ struct file_info { ...@@ -36,11 +36,6 @@ struct file_info {
u8 __user *fcp_buffer; u8 __user *fcp_buffer;
/* old ISO API */
u64 listen_channels;
quadlet_t __user *iso_buffer;
size_t iso_buffer_length;
u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */ u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
/* new rawiso API */ /* new rawiso API */
......
...@@ -98,21 +98,6 @@ static struct hpsb_address_ops arm_ops = { ...@@ -98,21 +98,6 @@ static struct hpsb_address_ops arm_ops = {
static void queue_complete_cb(struct pending_request *req); static void queue_complete_cb(struct pending_request *req);
#include <asm/current.h>
static void print_old_iso_deprecation(void)
{
static pid_t p;
if (p == current->pid)
return;
p = current->pid;
printk(KERN_WARNING "raw1394: WARNING - Program \"%s\" uses unsupported"
" isochronous request types which will be removed in a next"
" kernel release\n", current->comm);
printk(KERN_WARNING "raw1394: Update your software to use libraw1394's"
" newer interface\n");
}
static struct pending_request *__alloc_pending_request(gfp_t flags) static struct pending_request *__alloc_pending_request(gfp_t flags)
{ {
struct pending_request *req; struct pending_request *req;
...@@ -297,67 +282,6 @@ static void host_reset(struct hpsb_host *host) ...@@ -297,67 +282,6 @@ static void host_reset(struct hpsb_host *host)
spin_unlock_irqrestore(&host_info_lock, flags); spin_unlock_irqrestore(&host_info_lock, flags);
} }
static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
size_t length)
{
unsigned long flags;
struct host_info *hi;
struct file_info *fi;
struct pending_request *req, *req_next;
struct iso_block_store *ibs = NULL;
LIST_HEAD(reqs);
if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
HPSB_INFO("dropped iso packet");
return;
}
spin_lock_irqsave(&host_info_lock, flags);
hi = find_host_info(host);
if (hi != NULL) {
list_for_each_entry(fi, &hi->file_info_list, list) {
if (!(fi->listen_channels & (1ULL << channel)))
continue;
req = __alloc_pending_request(GFP_ATOMIC);
if (!req)
break;
if (!ibs) {
ibs = kmalloc(sizeof(*ibs) + length,
GFP_ATOMIC);
if (!ibs) {
kfree(req);
break;
}
atomic_add(length, &iso_buffer_size);
atomic_set(&ibs->refcount, 0);
ibs->data_size = length;
memcpy(ibs->data, data, length);
}
atomic_inc(&ibs->refcount);
req->file_info = fi;
req->ibs = ibs;
req->data = ibs->data;
req->req.type = RAW1394_REQ_ISO_RECEIVE;
req->req.generation = get_hpsb_generation(host);
req->req.misc = 0;
req->req.recvb = ptr2int(fi->iso_buffer);
req->req.length = min(length, fi->iso_buffer_length);
list_add_tail(&req->list, &reqs);
}
}
spin_unlock_irqrestore(&host_info_lock, flags);
list_for_each_entry_safe(req, req_next, &reqs, list)
queue_complete_req(req);
}
static void fcp_request(struct hpsb_host *host, int nodeid, int direction, static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
int cts, u8 * data, size_t length) int cts, u8 * data, size_t length)
{ {
...@@ -434,7 +358,11 @@ struct compat_raw1394_req { ...@@ -434,7 +358,11 @@ struct compat_raw1394_req {
__u64 sendb; __u64 sendb;
__u64 recvb; __u64 recvb;
} __attribute__((packed)); }
#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
__attribute__((packed))
#endif
;
static const char __user *raw1394_compat_write(const char __user *buf) static const char __user *raw1394_compat_write(const char __user *buf)
{ {
...@@ -459,7 +387,7 @@ static const char __user *raw1394_compat_write(const char __user *buf) ...@@ -459,7 +387,7 @@ static const char __user *raw1394_compat_write(const char __user *buf)
static int static int
raw1394_compat_read(const char __user *buf, struct raw1394_request *r) raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
{ {
struct compat_raw1394_req __user *cr = (typeof(cr)) r; struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) || if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) ||
P(type) || P(type) ||
P(error) || P(error) ||
...@@ -587,7 +515,7 @@ static int state_opened(struct file_info *fi, struct pending_request *req) ...@@ -587,7 +515,7 @@ static int state_opened(struct file_info *fi, struct pending_request *req)
req->req.length = 0; req->req.length = 0;
queue_complete_req(req); queue_complete_req(req);
return sizeof(struct raw1394_request); return 0;
} }
static int state_initialized(struct file_info *fi, struct pending_request *req) static int state_initialized(struct file_info *fi, struct pending_request *req)
...@@ -601,7 +529,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) ...@@ -601,7 +529,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
req->req.generation = atomic_read(&internal_generation); req->req.generation = atomic_read(&internal_generation);
req->req.length = 0; req->req.length = 0;
queue_complete_req(req); queue_complete_req(req);
return sizeof(struct raw1394_request); return 0;
} }
switch (req->req.type) { switch (req->req.type) {
...@@ -673,44 +601,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) ...@@ -673,44 +601,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
} }
queue_complete_req(req); queue_complete_req(req);
return sizeof(struct raw1394_request); return 0;
}
static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
{
int channel = req->req.misc;
if ((channel > 63) || (channel < -64)) {
req->req.error = RAW1394_ERROR_INVALID_ARG;
} else if (channel >= 0) {
/* allocate channel req.misc */
if (fi->listen_channels & (1ULL << channel)) {
req->req.error = RAW1394_ERROR_ALREADY;
} else {
if (hpsb_listen_channel
(&raw1394_highlevel, fi->host, channel)) {
req->req.error = RAW1394_ERROR_ALREADY;
} else {
fi->listen_channels |= 1ULL << channel;
fi->iso_buffer = int2ptr(req->req.recvb);
fi->iso_buffer_length = req->req.length;
}
}
} else {
/* deallocate channel (one's complement neg) req.misc */
channel = ~channel;
if (fi->listen_channels & (1ULL << channel)) {
hpsb_unlisten_channel(&raw1394_highlevel, fi->host,
channel);
fi->listen_channels &= ~(1ULL << channel);
} else {
req->req.error = RAW1394_ERROR_INVALID_ARG;
}
}
req->req.length = 0;
queue_complete_req(req);
} }
static void handle_fcp_listen(struct file_info *fi, struct pending_request *req) static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
...@@ -865,7 +756,7 @@ static int handle_async_request(struct file_info *fi, ...@@ -865,7 +756,7 @@ static int handle_async_request(struct file_info *fi,
if (req->req.error) { if (req->req.error) {
req->req.length = 0; req->req.length = 0;
queue_complete_req(req); queue_complete_req(req);
return sizeof(struct raw1394_request); return 0;
} }
hpsb_set_packet_complete_task(packet, hpsb_set_packet_complete_task(packet,
...@@ -883,51 +774,7 @@ static int handle_async_request(struct file_info *fi, ...@@ -883,51 +774,7 @@ static int handle_async_request(struct file_info *fi,
hpsb_free_tlabel(packet); hpsb_free_tlabel(packet);
queue_complete_req(req); queue_complete_req(req);
} }
return sizeof(struct raw1394_request); return 0;
}
static int handle_iso_send(struct file_info *fi, struct pending_request *req,
int channel)
{
unsigned long flags;
struct hpsb_packet *packet;
packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f,
(req->req.misc >> 16) & 0x3,
req->req.misc & 0xf);
if (!packet)
return -ENOMEM;
packet->speed_code = req->req.address & 0x3;
req->packet = packet;
if (copy_from_user(packet->data, int2ptr(req->req.sendb),
req->req.length)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
req->req.length = 0;
queue_complete_req(req);
return sizeof(struct raw1394_request);
}
req->req.length = 0;
hpsb_set_packet_complete_task(packet,
(void (*)(void *))queue_complete_req,
req);
spin_lock_irqsave(&fi->reqlists_lock, flags);
list_add_tail(&req->list, &fi->req_pending);
spin_unlock_irqrestore(&fi->reqlists_lock, flags);
/* Update the generation of the packet just before sending. */
packet->generation = req->req.generation;
if (hpsb_send_packet(packet) < 0) {
req->req.error = RAW1394_ERROR_SEND_ERROR;
queue_complete_req(req);
}
return sizeof(struct raw1394_request);
} }
static int handle_async_send(struct file_info *fi, struct pending_request *req) static int handle_async_send(struct file_info *fi, struct pending_request *req)
...@@ -943,7 +790,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req) ...@@ -943,7 +790,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
req->req.error = RAW1394_ERROR_INVALID_ARG; req->req.error = RAW1394_ERROR_INVALID_ARG;
req->req.length = 0; req->req.length = 0;
queue_complete_req(req); queue_complete_req(req);
return sizeof(struct raw1394_request); return 0;
} }
data_size = req->req.length - header_length; data_size = req->req.length - header_length;
...@@ -957,7 +804,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req) ...@@ -957,7 +804,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
req->req.error = RAW1394_ERROR_MEMFAULT; req->req.error = RAW1394_ERROR_MEMFAULT;
req->req.length = 0; req->req.length = 0;
queue_complete_req(req); queue_complete_req(req);
return sizeof(struct raw1394_request); return 0;
} }
if (copy_from_user if (copy_from_user
...@@ -966,7 +813,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req) ...@@ -966,7 +813,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
req->req.error = RAW1394_ERROR_MEMFAULT; req->req.error = RAW1394_ERROR_MEMFAULT;
req->req.length = 0; req->req.length = 0;
queue_complete_req(req); queue_complete_req(req);
return sizeof(struct raw1394_request); return 0;
} }
packet->type = hpsb_async; packet->type = hpsb_async;
...@@ -994,7 +841,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req) ...@@ -994,7 +841,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
queue_complete_req(req); queue_complete_req(req);
} }
return sizeof(struct raw1394_request); return 0;
} }
static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
...@@ -1869,7 +1716,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req) ...@@ -1869,7 +1716,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
spin_lock_irqsave(&host_info_lock, flags); spin_lock_irqsave(&host_info_lock, flags);
list_add_tail(&addr->addr_list, &fi->addr_list); list_add_tail(&addr->addr_list, &fi->addr_list);
spin_unlock_irqrestore(&host_info_lock, flags); spin_unlock_irqrestore(&host_info_lock, flags);
return sizeof(struct raw1394_request); return 0;
} }
retval = retval =
hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops, hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops,
...@@ -1887,7 +1734,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req) ...@@ -1887,7 +1734,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
return (-EALREADY); return (-EALREADY);
} }
free_pending_request(req); /* immediate success or fail */ free_pending_request(req); /* immediate success or fail */
return sizeof(struct raw1394_request); return 0;
} }
static int arm_unregister(struct file_info *fi, struct pending_request *req) static int arm_unregister(struct file_info *fi, struct pending_request *req)
...@@ -1955,7 +1802,7 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req) ...@@ -1955,7 +1802,7 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req)
vfree(addr->addr_space_buffer); vfree(addr->addr_space_buffer);
kfree(addr); kfree(addr);
free_pending_request(req); /* immediate success or fail */ free_pending_request(req); /* immediate success or fail */
return sizeof(struct raw1394_request); return 0;
} }
retval = retval =
hpsb_unregister_addrspace(&raw1394_highlevel, fi->host, hpsb_unregister_addrspace(&raw1394_highlevel, fi->host,
...@@ -1971,7 +1818,7 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req) ...@@ -1971,7 +1818,7 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req)
vfree(addr->addr_space_buffer); vfree(addr->addr_space_buffer);
kfree(addr); kfree(addr);
free_pending_request(req); /* immediate success or fail */ free_pending_request(req); /* immediate success or fail */
return sizeof(struct raw1394_request); return 0;
} }
/* Copy data from ARM buffer(s) to user buffer. */ /* Copy data from ARM buffer(s) to user buffer. */
...@@ -2013,7 +1860,7 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req) ...@@ -2013,7 +1860,7 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req)
* queue no response, and therefore nobody * queue no response, and therefore nobody
* will free it. */ * will free it. */
free_pending_request(req); free_pending_request(req);
return sizeof(struct raw1394_request); return 0;
} else { } else {
DBGMSG("arm_get_buf request exceeded mapping"); DBGMSG("arm_get_buf request exceeded mapping");
spin_unlock_irqrestore(&host_info_lock, flags); spin_unlock_irqrestore(&host_info_lock, flags);
...@@ -2065,7 +1912,7 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req) ...@@ -2065,7 +1912,7 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req)
* queue no response, and therefore nobody * queue no response, and therefore nobody
* will free it. */ * will free it. */
free_pending_request(req); free_pending_request(req);
return sizeof(struct raw1394_request); return 0;
} else { } else {
DBGMSG("arm_set_buf request exceeded mapping"); DBGMSG("arm_set_buf request exceeded mapping");
spin_unlock_irqrestore(&host_info_lock, flags); spin_unlock_irqrestore(&host_info_lock, flags);
...@@ -2086,7 +1933,7 @@ static int reset_notification(struct file_info *fi, struct pending_request *req) ...@@ -2086,7 +1933,7 @@ static int reset_notification(struct file_info *fi, struct pending_request *req)
(req->req.misc == RAW1394_NOTIFY_ON)) { (req->req.misc == RAW1394_NOTIFY_ON)) {
fi->notification = (u8) req->req.misc; fi->notification = (u8) req->req.misc;
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
return sizeof(struct raw1394_request); return 0;
} }
/* error EINVAL (22) invalid argument */ /* error EINVAL (22) invalid argument */
return (-EINVAL); return (-EINVAL);
...@@ -2119,12 +1966,12 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req) ...@@ -2119,12 +1966,12 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req)
req->req.length = 0; req->req.length = 0;
queue_complete_req(req); queue_complete_req(req);
} }
return sizeof(struct raw1394_request); return 0;
} }
static int get_config_rom(struct file_info *fi, struct pending_request *req) static int get_config_rom(struct file_info *fi, struct pending_request *req)
{ {
int ret = sizeof(struct raw1394_request); int ret = 0;
quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL); quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
int status; int status;
...@@ -2154,7 +2001,7 @@ static int get_config_rom(struct file_info *fi, struct pending_request *req) ...@@ -2154,7 +2001,7 @@ static int get_config_rom(struct file_info *fi, struct pending_request *req)
static int update_config_rom(struct file_info *fi, struct pending_request *req) static int update_config_rom(struct file_info *fi, struct pending_request *req)
{ {
int ret = sizeof(struct raw1394_request); int ret = 0;
quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL); quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
...@@ -2221,7 +2068,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req) ...@@ -2221,7 +2068,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
hpsb_update_config_rom_image(fi->host); hpsb_update_config_rom_image(fi->host);
free_pending_request(req); free_pending_request(req);
return sizeof(struct raw1394_request); return 0;
} }
} }
...@@ -2286,7 +2133,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req) ...@@ -2286,7 +2133,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
/* we have to free the request, because we queue no response, /* we have to free the request, because we queue no response,
* and therefore nobody will free it */ * and therefore nobody will free it */
free_pending_request(req); free_pending_request(req);
return sizeof(struct raw1394_request); return 0;
} else { } else {
for (dentry = for (dentry =
fi->csr1212_dirs[dr]->value.directory.dentries_head; fi->csr1212_dirs[dr]->value.directory.dentries_head;
...@@ -2311,11 +2158,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req) ...@@ -2311,11 +2158,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
case RAW1394_REQ_ECHO: case RAW1394_REQ_ECHO:
queue_complete_req(req); queue_complete_req(req);
return sizeof(struct raw1394_request); return 0;
case RAW1394_REQ_ISO_SEND:
print_old_iso_deprecation();
return handle_iso_send(fi, req, node);
case RAW1394_REQ_ARM_REGISTER: case RAW1394_REQ_ARM_REGISTER:
return arm_register(fi, req); return arm_register(fi, req);
...@@ -2332,27 +2175,30 @@ static int state_connected(struct file_info *fi, struct pending_request *req) ...@@ -2332,27 +2175,30 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
case RAW1394_REQ_RESET_NOTIFY: case RAW1394_REQ_RESET_NOTIFY:
return reset_notification(fi, req); return reset_notification(fi, req);
case RAW1394_REQ_ISO_SEND:
case RAW1394_REQ_ISO_LISTEN: case RAW1394_REQ_ISO_LISTEN:
print_old_iso_deprecation(); printk(KERN_DEBUG "raw1394: old iso ABI has been removed\n");
handle_iso_listen(fi, req); req->req.error = RAW1394_ERROR_COMPAT;
return sizeof(struct raw1394_request); req->req.misc = RAW1394_KERNELAPI_VERSION;
queue_complete_req(req);
return 0;
case RAW1394_REQ_FCP_LISTEN: case RAW1394_REQ_FCP_LISTEN:
handle_fcp_listen(fi, req); handle_fcp_listen(fi, req);
return sizeof(struct raw1394_request); return 0;
case RAW1394_REQ_RESET_BUS: case RAW1394_REQ_RESET_BUS:
if (req->req.misc == RAW1394_LONG_RESET) { if (req->req.misc == RAW1394_LONG_RESET) {
DBGMSG("busreset called (type: LONG)"); DBGMSG("busreset called (type: LONG)");
hpsb_reset_bus(fi->host, LONG_RESET); hpsb_reset_bus(fi->host, LONG_RESET);
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
return sizeof(struct raw1394_request); return 0;
} }
if (req->req.misc == RAW1394_SHORT_RESET) { if (req->req.misc == RAW1394_SHORT_RESET) {
DBGMSG("busreset called (type: SHORT)"); DBGMSG("busreset called (type: SHORT)");
hpsb_reset_bus(fi->host, SHORT_RESET); hpsb_reset_bus(fi->host, SHORT_RESET);
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
return sizeof(struct raw1394_request); return 0;
} }
/* error EINVAL (22) invalid argument */ /* error EINVAL (22) invalid argument */
return (-EINVAL); return (-EINVAL);
...@@ -2371,7 +2217,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req) ...@@ -2371,7 +2217,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
req->req.generation = get_hpsb_generation(fi->host); req->req.generation = get_hpsb_generation(fi->host);
req->req.length = 0; req->req.length = 0;
queue_complete_req(req); queue_complete_req(req);
return sizeof(struct raw1394_request); return 0;
} }
switch (req->req.type) { switch (req->req.type) {
...@@ -2384,7 +2230,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req) ...@@ -2384,7 +2230,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
if (req->req.length == 0) { if (req->req.length == 0) {
req->req.error = RAW1394_ERROR_INVALID_ARG; req->req.error = RAW1394_ERROR_INVALID_ARG;
queue_complete_req(req); queue_complete_req(req);
return sizeof(struct raw1394_request); return 0;
} }
return handle_async_request(fi, req, node); return handle_async_request(fi, req, node);
...@@ -2395,7 +2241,7 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, ...@@ -2395,7 +2241,7 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
{ {
struct file_info *fi = (struct file_info *)file->private_data; struct file_info *fi = (struct file_info *)file->private_data;
struct pending_request *req; struct pending_request *req;
ssize_t retval = 0; ssize_t retval = -EBADFD;
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
if (count == sizeof(struct compat_raw1394_req) && if (count == sizeof(struct compat_raw1394_req) &&
...@@ -2437,6 +2283,9 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, ...@@ -2437,6 +2283,9 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
if (retval < 0) { if (retval < 0) {
free_pending_request(req); free_pending_request(req);
} else {
BUG_ON(retval);
retval = count;
} }
return retval; return retval;
...@@ -2802,6 +2651,103 @@ static int raw1394_ioctl(struct inode *inode, struct file *file, ...@@ -2802,6 +2651,103 @@ static int raw1394_ioctl(struct inode *inode, struct file *file,
return -EINVAL; return -EINVAL;
} }
#ifdef CONFIG_COMPAT
struct raw1394_iso_packets32 {
__u32 n_packets;
compat_uptr_t infos;
} __attribute__((packed));
struct raw1394_cycle_timer32 {
__u32 cycle_timer;
__u64 local_time;
}
#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
__attribute__((packed))
#endif
;
#define RAW1394_IOC_ISO_RECV_PACKETS32 \
_IOW ('#', 0x25, struct raw1394_iso_packets32)
#define RAW1394_IOC_ISO_XMIT_PACKETS32 \
_IOW ('#', 0x27, struct raw1394_iso_packets32)
#define RAW1394_IOC_GET_CYCLE_TIMER32 \
_IOR ('#', 0x30, struct raw1394_cycle_timer32)
static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd,
struct raw1394_iso_packets32 __user *arg)
{
compat_uptr_t infos32;
void *infos;
long err = -EFAULT;
struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets));
if (!copy_in_user(&dst->n_packets, &arg->n_packets, sizeof arg->n_packets) &&
!copy_from_user(&infos32, &arg->infos, sizeof infos32)) {
infos = compat_ptr(infos32);
if (!copy_to_user(&dst->infos, &infos, sizeof infos))
err = raw1394_ioctl(NULL, file, cmd, (unsigned long)dst);
}
return err;
}
static long raw1394_read_cycle_timer32(struct file_info *fi, void __user * uaddr)
{
struct raw1394_cycle_timer32 ct;
int err;
err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
if (!err)
if (copy_to_user(uaddr, &ct, sizeof(ct)))
err = -EFAULT;
return err;
}
static long raw1394_compat_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct file_info *fi = file->private_data;
void __user *argp = (void __user *)arg;
long err;
lock_kernel();
switch (cmd) {
/* These requests have same format as long as 'int' has same size. */
case RAW1394_IOC_ISO_RECV_INIT:
case RAW1394_IOC_ISO_RECV_START:
case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:
case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
case RAW1394_IOC_ISO_RECV_FLUSH:
case RAW1394_IOC_ISO_XMIT_RECV_STOP:
case RAW1394_IOC_ISO_XMIT_INIT:
case RAW1394_IOC_ISO_XMIT_START:
case RAW1394_IOC_ISO_XMIT_SYNC:
case RAW1394_IOC_ISO_GET_STATUS:
case RAW1394_IOC_ISO_SHUTDOWN:
case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
err = raw1394_ioctl(NULL, file, cmd, arg);
break;
/* These request have different format. */
case RAW1394_IOC_ISO_RECV_PACKETS32:
err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_RECV_PACKETS, argp);
break;
case RAW1394_IOC_ISO_XMIT_PACKETS32:
err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_XMIT_PACKETS, argp);
break;
case RAW1394_IOC_GET_CYCLE_TIMER32:
err = raw1394_read_cycle_timer32(fi, argp);
break;
default:
err = -EINVAL;
break;
}
unlock_kernel();
return err;
}
#endif
static unsigned int raw1394_poll(struct file *file, poll_table * pt) static unsigned int raw1394_poll(struct file *file, poll_table * pt)
{ {
struct file_info *fi = file->private_data; struct file_info *fi = file->private_data;
...@@ -2861,14 +2807,7 @@ static int raw1394_release(struct inode *inode, struct file *file) ...@@ -2861,14 +2807,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
if (fi->iso_state != RAW1394_ISO_INACTIVE) if (fi->iso_state != RAW1394_ISO_INACTIVE)
raw1394_iso_shutdown(fi); raw1394_iso_shutdown(fi);
for (i = 0; i < 64; i++) {
if (fi->listen_channels & (1ULL << i)) {
hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i);
}
}
spin_lock_irqsave(&host_info_lock, flags); spin_lock_irqsave(&host_info_lock, flags);
fi->listen_channels = 0;
fail = 0; fail = 0;
/* set address-entries invalid */ /* set address-entries invalid */
...@@ -3030,7 +2969,6 @@ static struct hpsb_highlevel raw1394_highlevel = { ...@@ -3030,7 +2969,6 @@ static struct hpsb_highlevel raw1394_highlevel = {
.add_host = add_host, .add_host = add_host,
.remove_host = remove_host, .remove_host = remove_host,
.host_reset = host_reset, .host_reset = host_reset,
.iso_receive = iso_receive,
.fcp_request = fcp_request, .fcp_request = fcp_request,
}; };
...@@ -3041,7 +2979,9 @@ static const struct file_operations raw1394_fops = { ...@@ -3041,7 +2979,9 @@ static const struct file_operations raw1394_fops = {
.write = raw1394_write, .write = raw1394_write,
.mmap = raw1394_mmap, .mmap = raw1394_mmap,
.ioctl = raw1394_ioctl, .ioctl = raw1394_ioctl,
// .compat_ioctl = ... someone needs to do this #ifdef CONFIG_COMPAT
.compat_ioctl = raw1394_compat_ioctl,
#endif
.poll = raw1394_poll, .poll = raw1394_poll,
.open = raw1394_open, .open = raw1394_open,
.release = raw1394_release, .release = raw1394_release,
...@@ -3054,9 +2994,9 @@ static int __init init_raw1394(void) ...@@ -3054,9 +2994,9 @@ static int __init init_raw1394(void)
hpsb_register_highlevel(&raw1394_highlevel); hpsb_register_highlevel(&raw1394_highlevel);
if (IS_ERR if (IS_ERR
(class_device_create (device_create(
(hpsb_protocol_class, NULL, hpsb_protocol_class, NULL,
MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), NULL, MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
RAW1394_DEVICE_NAME))) { RAW1394_DEVICE_NAME))) {
ret = -EFAULT; ret = -EFAULT;
goto out_unreg; goto out_unreg;
...@@ -3083,7 +3023,7 @@ static int __init init_raw1394(void) ...@@ -3083,7 +3023,7 @@ static int __init init_raw1394(void)
goto out; goto out;
out_dev: out_dev:
class_device_destroy(hpsb_protocol_class, device_destroy(hpsb_protocol_class,
MKDEV(IEEE1394_MAJOR, MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_RAW1394 * 16)); IEEE1394_MINOR_BLOCK_RAW1394 * 16));
out_unreg: out_unreg:
...@@ -3094,7 +3034,7 @@ static int __init init_raw1394(void) ...@@ -3094,7 +3034,7 @@ static int __init init_raw1394(void)
static void __exit cleanup_raw1394(void) static void __exit cleanup_raw1394(void)
{ {
class_device_destroy(hpsb_protocol_class, device_destroy(hpsb_protocol_class,
MKDEV(IEEE1394_MAJOR, MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_RAW1394 * 16)); IEEE1394_MINOR_BLOCK_RAW1394 * 16));
cdev_del(&raw1394_cdev); cdev_del(&raw1394_cdev);
......
...@@ -17,11 +17,11 @@ ...@@ -17,11 +17,11 @@
#define RAW1394_REQ_ASYNC_WRITE 101 #define RAW1394_REQ_ASYNC_WRITE 101
#define RAW1394_REQ_LOCK 102 #define RAW1394_REQ_LOCK 102
#define RAW1394_REQ_LOCK64 103 #define RAW1394_REQ_LOCK64 103
#define RAW1394_REQ_ISO_SEND 104 #define RAW1394_REQ_ISO_SEND 104 /* removed ABI, now a no-op */
#define RAW1394_REQ_ASYNC_SEND 105 #define RAW1394_REQ_ASYNC_SEND 105
#define RAW1394_REQ_ASYNC_STREAM 106 #define RAW1394_REQ_ASYNC_STREAM 106
#define RAW1394_REQ_ISO_LISTEN 200 #define RAW1394_REQ_ISO_LISTEN 200 /* removed ABI, now a no-op */
#define RAW1394_REQ_FCP_LISTEN 201 #define RAW1394_REQ_FCP_LISTEN 201
#define RAW1394_REQ_RESET_BUS 202 #define RAW1394_REQ_RESET_BUS 202
#define RAW1394_REQ_GET_ROM 203 #define RAW1394_REQ_GET_ROM 203
......
...@@ -118,14 +118,13 @@ MODULE_PARM_DESC(max_speed, "Force max speed " ...@@ -118,14 +118,13 @@ MODULE_PARM_DESC(max_speed, "Force max speed "
"(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)"); "(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)");
/* /*
* Set serialize_io to 1 if you'd like only one scsi command sent * Set serialize_io to 0 or N to use dynamically appended lists of command ORBs.
* down to us at a time (debugging). This might be necessary for very * This is and always has been buggy in multiple subtle ways. See above TODOs.
* badly behaved sbp2 devices.
*/ */
static int sbp2_serialize_io = 1; static int sbp2_serialize_io = 1;
module_param_named(serialize_io, sbp2_serialize_io, int, 0444); module_param_named(serialize_io, sbp2_serialize_io, bool, 0444);
MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers " MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers "
"(default = 1, faster = 0)"); "(default = Y, faster but buggy = N)");
/* /*
* Bump up max_sectors if you'd like to support very large sized * Bump up max_sectors if you'd like to support very large sized
...@@ -154,9 +153,9 @@ MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported " ...@@ -154,9 +153,9 @@ MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported "
* are possible on OXFW911 and newer Oxsemi bridges. * are possible on OXFW911 and newer Oxsemi bridges.
*/ */
static int sbp2_exclusive_login = 1; static int sbp2_exclusive_login = 1;
module_param_named(exclusive_login, sbp2_exclusive_login, int, 0644); module_param_named(exclusive_login, sbp2_exclusive_login, bool, 0644);
MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device " MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
"(default = 1)"); "(default = Y, use N for concurrent initiators)");
/* /*
* If any of the following workarounds is required for your device to work, * If any of the following workarounds is required for your device to work,
......
...@@ -67,7 +67,7 @@ struct sbp2_command_orb { ...@@ -67,7 +67,7 @@ struct sbp2_command_orb {
#define ORB_SET_LUN(v) ((v) & 0xffff) #define ORB_SET_LUN(v) ((v) & 0xffff)
#define ORB_SET_FUNCTION(v) (((v) & 0xf) << 16) #define ORB_SET_FUNCTION(v) (((v) & 0xf) << 16)
#define ORB_SET_RECONNECT(v) (((v) & 0xf) << 20) #define ORB_SET_RECONNECT(v) (((v) & 0xf) << 20)
#define ORB_SET_EXCLUSIVE(v) (((v) & 0x1) << 28) #define ORB_SET_EXCLUSIVE(v) ((v) ? 1 << 28 : 0)
#define ORB_SET_LOGIN_RESP_LENGTH(v) ((v) & 0xffff) #define ORB_SET_LOGIN_RESP_LENGTH(v) ((v) & 0xffff)
#define ORB_SET_PASSWD_LENGTH(v) (((v) & 0xffff) << 16) #define ORB_SET_PASSWD_LENGTH(v) (((v) & 0xffff) << 16)
......
...@@ -1340,9 +1340,9 @@ static void video1394_add_host (struct hpsb_host *host) ...@@ -1340,9 +1340,9 @@ static void video1394_add_host (struct hpsb_host *host)
hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id); hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id; minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
class_device_create(hpsb_protocol_class, NULL, MKDEV( device_create(hpsb_protocol_class, NULL,
IEEE1394_MAJOR, minor), MKDEV(IEEE1394_MAJOR, minor),
NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id); "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
} }
...@@ -1351,7 +1351,7 @@ static void video1394_remove_host (struct hpsb_host *host) ...@@ -1351,7 +1351,7 @@ static void video1394_remove_host (struct hpsb_host *host)
struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host); struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
if (ohci) if (ohci)
class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR, device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id)); IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
return; return;
} }
......
...@@ -30,16 +30,38 @@ ...@@ -30,16 +30,38 @@
#define FW_CDEV_EVENT_REQUEST 0x02 #define FW_CDEV_EVENT_REQUEST 0x02
#define FW_CDEV_EVENT_ISO_INTERRUPT 0x03 #define FW_CDEV_EVENT_ISO_INTERRUPT 0x03
/* The 'closure' fields are for user space to use. Data passed in the /**
* 'closure' field for a request will be returned in the corresponding * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types
* event. It's a 64-bit type so that it's a fixed size type big * @closure: For arbitrary use by userspace
* enough to hold a pointer on all platforms. */ * @type: Discriminates the fw_cdev_event_ types
*
* This struct may be used to access generic members of all fw_cdev_event_
* types regardless of the specific type.
*
* Data passed in the @closure field for a request will be returned in the
* corresponding event. It is big enough to hold a pointer on all platforms.
* The ioctl used to set @closure depends on the @type of event.
*/
struct fw_cdev_event_common { struct fw_cdev_event_common {
__u64 closure; __u64 closure;
__u32 type; __u32 type;
}; };
/**
* struct fw_cdev_event_bus_reset - Sent when a bus reset occurred
* @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_GET_INFO ioctl
* @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_BUS_RESET
* @node_id: New node ID of this node
* @local_node_id: Node ID of the local node, i.e. of the controller
* @bm_node_id: Node ID of the bus manager
* @irm_node_id: Node ID of the iso resource manager
* @root_node_id: Node ID of the root node
* @generation: New bus generation
*
* This event is sent when the bus the device belongs to goes through a bus
* reset. It provides information about the new bus configuration, such as
* new node ID for this device, new root ID, and others.
*/
struct fw_cdev_event_bus_reset { struct fw_cdev_event_bus_reset {
__u64 closure; __u64 closure;
__u32 type; __u32 type;
...@@ -51,6 +73,20 @@ struct fw_cdev_event_bus_reset { ...@@ -51,6 +73,20 @@ struct fw_cdev_event_bus_reset {
__u32 generation; __u32 generation;
}; };
/**
* struct fw_cdev_event_response - Sent when a response packet was received
* @closure: See &fw_cdev_event_common;
* set by %FW_CDEV_IOC_SEND_REQUEST ioctl
* @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_RESPONSE
* @rcode: Response code returned by the remote node
* @length: Data length, i.e. the response's payload size in bytes
* @data: Payload data, if any
*
* This event is sent when the stack receives a response to an outgoing request
* sent by %FW_CDEV_IOC_SEND_REQUEST ioctl. The payload data for responses
* carrying data (read and lock responses) follows immediately and can be
* accessed through the @data field.
*/
struct fw_cdev_event_response { struct fw_cdev_event_response {
__u64 closure; __u64 closure;
__u32 type; __u32 type;
...@@ -59,6 +95,25 @@ struct fw_cdev_event_response { ...@@ -59,6 +95,25 @@ struct fw_cdev_event_response {
__u32 data[0]; __u32 data[0];
}; };
/**
* struct fw_cdev_event_request - Sent on incoming request to an address region
* @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl
* @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST
* @tcode: Transaction code of the incoming request
* @offset: The offset into the 48-bit per-node address space
* @handle: Reference to the kernel-side pending request
* @length: Data length, i.e. the request's payload size in bytes
* @data: Incoming data, if any
*
* This event is sent when the stack receives an incoming request to an address
* region registered using the %FW_CDEV_IOC_ALLOCATE ioctl. The request is
* guaranteed to be completely contained in the specified region. Userspace is
* responsible for sending the response by %FW_CDEV_IOC_SEND_RESPONSE ioctl,
* using the same @handle.
*
* The payload data for requests carrying data (write and lock requests)
* follows immediately and can be accessed through the @data field.
*/
struct fw_cdev_event_request { struct fw_cdev_event_request {
__u64 closure; __u64 closure;
__u32 type; __u32 type;
...@@ -69,14 +124,39 @@ struct fw_cdev_event_request { ...@@ -69,14 +124,39 @@ struct fw_cdev_event_request {
__u32 data[0]; __u32 data[0];
}; };
/**
* struct fw_cdev_event_iso_interrupt - Sent when an iso packet was completed
* @closure: See &fw_cdev_event_common;
* set by %FW_CDEV_CREATE_ISO_CONTEXT ioctl
* @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_ISO_INTERRUPT
* @cycle: Cycle counter of the interrupt packet
* @header_length: Total length of following headers, in bytes
* @header: Stripped headers, if any
*
* This event is sent when the controller has completed an &fw_cdev_iso_packet
* with the %FW_CDEV_ISO_INTERRUPT bit set. In the receive case, the headers
* stripped of all packets up until and including the interrupt packet are
* returned in the @header field.
*/
struct fw_cdev_event_iso_interrupt { struct fw_cdev_event_iso_interrupt {
__u64 closure; __u64 closure;
__u32 type; __u32 type;
__u32 cycle; __u32 cycle;
__u32 header_length; /* Length in bytes of following headers. */ __u32 header_length;
__u32 header[0]; __u32 header[0];
}; };
/**
* union fw_cdev_event - Convenience union of fw_cdev_event_ types
* @common: Valid for all types
* @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET
* @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE
* @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST
* @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT
*
* Convenience union for userspace use. Events could be read(2) into a char
* buffer and then cast to this union for further processing.
*/
union fw_cdev_event { union fw_cdev_event {
struct fw_cdev_event_common common; struct fw_cdev_event_common common;
struct fw_cdev_event_bus_reset bus_reset; struct fw_cdev_event_bus_reset bus_reset;
...@@ -105,35 +185,47 @@ union fw_cdev_event { ...@@ -105,35 +185,47 @@ union fw_cdev_event {
*/ */
#define FW_CDEV_VERSION 1 #define FW_CDEV_VERSION 1
/**
* struct fw_cdev_get_info - General purpose information ioctl
* @version: The version field is just a running serial number.
* We never break backwards compatibility, but may add more
* structs and ioctls in later revisions.
* @rom_length: If @rom is non-zero, at most rom_length bytes of configuration
* ROM will be copied into that user space address. In either
* case, @rom_length is updated with the actual length of the
* configuration ROM.
* @rom: If non-zero, address of a buffer to be filled by a copy of the
* local node's configuration ROM
* @bus_reset: If non-zero, address of a buffer to be filled by a
* &struct fw_cdev_event_bus_reset with the current state
* of the bus. This does not cause a bus reset to happen.
* @bus_reset_closure: Value of &closure in this and subsequent bus reset events
* @card: The index of the card this device belongs to
*/
struct fw_cdev_get_info { struct fw_cdev_get_info {
/* The version field is just a running serial number. We
* never break backwards compatibility. Userspace passes in
* the version it expects and the kernel passes back the
* highest version it can provide. Even if the structs in
* this interface are extended in a later version, the kernel
* will not copy back more data than what was present in the
* interface version userspace expects. */
__u32 version; __u32 version;
/* If non-zero, at most rom_length bytes of config rom will be
* copied into that user space address. In either case,
* rom_length is updated with the actual length of the config
* rom. */
__u32 rom_length; __u32 rom_length;
__u64 rom; __u64 rom;
/* If non-zero, a fw_cdev_event_bus_reset struct will be
* copied here with the current state of the bus. This does
* not cause a bus reset to happen. The value of closure in
* this and sub-sequent bus reset events is set to
* bus_reset_closure. */
__u64 bus_reset; __u64 bus_reset;
__u64 bus_reset_closure; __u64 bus_reset_closure;
/* The index of the card this devices belongs to. */
__u32 card; __u32 card;
}; };
/**
* struct fw_cdev_send_request - Send an asynchronous request packet
* @tcode: Transaction code of the request
* @length: Length of outgoing payload, in bytes
* @offset: 48-bit offset at destination node
* @closure: Passed back to userspace in the response event
* @data: Userspace pointer to payload
* @generation: The bus generation where packet is valid
*
* Send a request to the device. This ioctl implements all outgoing requests.
* Both quadlet and block request specify the payload as a pointer to the data
* in the @data field. Once the transaction completes, the kernel writes an
* &fw_cdev_event_request event back. The @closure field is passed back to
* user space in the response event.
*/
struct fw_cdev_send_request { struct fw_cdev_send_request {
__u32 tcode; __u32 tcode;
__u32 length; __u32 length;
...@@ -143,6 +235,19 @@ struct fw_cdev_send_request { ...@@ -143,6 +235,19 @@ struct fw_cdev_send_request {
__u32 generation; __u32 generation;
}; };
/**
* struct fw_cdev_send_response - Send an asynchronous response packet
* @rcode: Response code as determined by the userspace handler
* @length: Length of outgoing payload, in bytes
* @data: Userspace pointer to payload
* @handle: The handle from the &fw_cdev_event_request
*
* Send a response to an incoming request. By setting up an address range using
* the %FW_CDEV_IOC_ALLOCATE ioctl, userspace can listen for incoming requests. An
* incoming request will generate an %FW_CDEV_EVENT_REQUEST, and userspace must
* send a reply using this ioctl. The event has a handle to the kernel-side
* pending transaction, which should be used with this ioctl.
*/
struct fw_cdev_send_response { struct fw_cdev_send_response {
__u32 rcode; __u32 rcode;
__u32 length; __u32 length;
...@@ -150,6 +255,21 @@ struct fw_cdev_send_response { ...@@ -150,6 +255,21 @@ struct fw_cdev_send_response {
__u32 handle; __u32 handle;
}; };
/**
* struct fw_cdev_allocate - Allocate a CSR address range
* @offset: Start offset of the address range
* @closure: To be passed back to userspace in request events
* @length: Length of the address range, in bytes
* @handle: Handle to the allocation, written by the kernel
*
* Allocate an address range in the 48-bit address space on the local node
* (the controller). This allows userspace to listen for requests with an
* offset within that address range. When the kernel receives a request
* within the range, an &fw_cdev_event_request event will be written back.
* The @closure field is passed back to userspace in the response event.
* The @handle field is an out parameter, returning a handle to the allocated
* range to be used for later deallocation of the range.
*/
struct fw_cdev_allocate { struct fw_cdev_allocate {
__u64 offset; __u64 offset;
__u64 closure; __u64 closure;
...@@ -157,6 +277,11 @@ struct fw_cdev_allocate { ...@@ -157,6 +277,11 @@ struct fw_cdev_allocate {
__u32 handle; __u32 handle;
}; };
/**
* struct fw_cdev_deallocate - Free an address range allocation
* @handle: Handle to the address range, as returned by the kernel when the
* range was allocated
*/
struct fw_cdev_deallocate { struct fw_cdev_deallocate {
__u32 handle; __u32 handle;
}; };
...@@ -164,10 +289,41 @@ struct fw_cdev_deallocate { ...@@ -164,10 +289,41 @@ struct fw_cdev_deallocate {
#define FW_CDEV_LONG_RESET 0 #define FW_CDEV_LONG_RESET 0
#define FW_CDEV_SHORT_RESET 1 #define FW_CDEV_SHORT_RESET 1
/**
* struct fw_cdev_initiate_bus_reset - Initiate a bus reset
* @type: %FW_CDEV_SHORT_RESET or %FW_CDEV_LONG_RESET
*
* Initiate a bus reset for the bus this device is on. The bus reset can be
* either the original (long) bus reset or the arbitrated (short) bus reset
* introduced in 1394a-2000.
*/
struct fw_cdev_initiate_bus_reset { struct fw_cdev_initiate_bus_reset {
__u32 type; __u32 type; /* FW_CDEV_SHORT_RESET or FW_CDEV_LONG_RESET */
}; };
/**
* struct fw_cdev_add_descriptor - Add contents to the local node's config ROM
* @immediate: If non-zero, immediate key to insert before pointer
* @key: Upper 8 bits of root directory pointer
* @data: Userspace pointer to contents of descriptor block
* @length: Length of descriptor block data, in bytes
* @handle: Handle to the descriptor, written by the kernel
*
* Add a descriptor block and optionally a preceding immediate key to the local
* node's configuration ROM.
*
* The @key field specifies the upper 8 bits of the descriptor root directory
* pointer and the @data and @length fields specify the contents. The @key
* should be of the form 0xXX000000. The offset part of the root directory entry
* will be filled in by the kernel.
*
* If not 0, the @immediate field specifies an immediate key which will be
* inserted before the root directory pointer.
*
* If successful, the kernel adds the descriptor and writes back a handle to the
* kernel-side object to be used for later removal of the descriptor block and
* immediate key.
*/
struct fw_cdev_add_descriptor { struct fw_cdev_add_descriptor {
__u32 immediate; __u32 immediate;
__u32 key; __u32 key;
...@@ -176,6 +332,14 @@ struct fw_cdev_add_descriptor { ...@@ -176,6 +332,14 @@ struct fw_cdev_add_descriptor {
__u32 handle; __u32 handle;
}; };
/**
* struct fw_cdev_remove_descriptor - Remove contents from the configuration ROM
* @handle: Handle to the descriptor, as returned by the kernel when the
* descriptor was added
*
* Remove a descriptor block and accompanying immediate key from the local
* node's configuration ROM.
*/
struct fw_cdev_remove_descriptor { struct fw_cdev_remove_descriptor {
__u32 handle; __u32 handle;
}; };
...@@ -183,12 +347,24 @@ struct fw_cdev_remove_descriptor { ...@@ -183,12 +347,24 @@ struct fw_cdev_remove_descriptor {
#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0 #define FW_CDEV_ISO_CONTEXT_TRANSMIT 0
#define FW_CDEV_ISO_CONTEXT_RECEIVE 1 #define FW_CDEV_ISO_CONTEXT_RECEIVE 1
#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0 1 /**
#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1 2 * struct fw_cdev_create_iso_context - Create a context for isochronous IO
#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2 4 * @type: %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE
#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3 8 * @header_size: Header size to strip for receive contexts
#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS 15 * @channel: Channel to bind to
* @speed: Speed to transmit at
* @closure: To be returned in &fw_cdev_event_iso_interrupt
* @handle: Handle to context, written back by kernel
*
* Prior to sending or receiving isochronous I/O, a context must be created.
* The context records information about the transmit or receive configuration
* and typically maps to an underlying hardware resource. A context is set up
* for either sending or receiving. It is bound to a specific isochronous
* channel.
*
* If a context was successfully created, the kernel writes back a handle to the
* context, which must be passed in for subsequent operations on that context.
*/
struct fw_cdev_create_iso_context { struct fw_cdev_create_iso_context {
__u32 type; __u32 type;
__u32 header_size; __u32 header_size;
...@@ -201,15 +377,49 @@ struct fw_cdev_create_iso_context { ...@@ -201,15 +377,49 @@ struct fw_cdev_create_iso_context {
#define FW_CDEV_ISO_PAYLOAD_LENGTH(v) (v) #define FW_CDEV_ISO_PAYLOAD_LENGTH(v) (v)
#define FW_CDEV_ISO_INTERRUPT (1 << 16) #define FW_CDEV_ISO_INTERRUPT (1 << 16)
#define FW_CDEV_ISO_SKIP (1 << 17) #define FW_CDEV_ISO_SKIP (1 << 17)
#define FW_CDEV_ISO_SYNC (1 << 17)
#define FW_CDEV_ISO_TAG(v) ((v) << 18) #define FW_CDEV_ISO_TAG(v) ((v) << 18)
#define FW_CDEV_ISO_SY(v) ((v) << 20) #define FW_CDEV_ISO_SY(v) ((v) << 20)
#define FW_CDEV_ISO_HEADER_LENGTH(v) ((v) << 24) #define FW_CDEV_ISO_HEADER_LENGTH(v) ((v) << 24)
/**
* struct fw_cdev_iso_packet - Isochronous packet
* @control: Contains the header length (8 uppermost bits), the sy field
* (4 bits), the tag field (2 bits), a sync flag (1 bit),
* a skip flag (1 bit), an interrupt flag (1 bit), and the
* payload length (16 lowermost bits)
* @header: Header and payload
*
* &struct fw_cdev_iso_packet is used to describe isochronous packet queues.
*
* Use the FW_CDEV_ISO_ macros to fill in @control. The sy and tag fields are
* specified by IEEE 1394a and IEC 61883.
*
* FIXME - finish this documentation
*/
struct fw_cdev_iso_packet { struct fw_cdev_iso_packet {
__u32 control; __u32 control;
__u32 header[0]; __u32 header[0];
}; };
/**
* struct fw_cdev_queue_iso - Queue isochronous packets for I/O
* @packets: Userspace pointer to packet data
* @data: Pointer into mmap()'ed payload buffer
* @size: Size of packet data in bytes
* @handle: Isochronous context handle
*
* Queue a number of isochronous packets for reception or transmission.
* This ioctl takes a pointer to an array of &fw_cdev_iso_packet structs,
* which describe how to transmit from or receive into a contiguous region
* of a mmap()'ed payload buffer. As part of the packet descriptors,
* a series of headers can be supplied, which will be prepended to the
* payload during DMA.
*
* The kernel may or may not queue all packets, but will write back updated
* values of the @packets, @data and @size fields, so the ioctl can be
* resubmitted easily.
*/
struct fw_cdev_queue_iso { struct fw_cdev_queue_iso {
__u64 packets; __u64 packets;
__u64 data; __u64 data;
...@@ -217,6 +427,23 @@ struct fw_cdev_queue_iso { ...@@ -217,6 +427,23 @@ struct fw_cdev_queue_iso {
__u32 handle; __u32 handle;
}; };
#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0 1
#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1 2
#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2 4
#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3 8
#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS 15
/**
* struct fw_cdev_start_iso - Start an isochronous transmission or reception
* @cycle: Cycle in which to start I/O. If @cycle is greater than or
* equal to 0, the I/O will start on that cycle.
* @sync: Determines the value to wait for for receive packets that have
* the %FW_CDEV_ISO_SYNC bit set
* @tags: Tag filter bit mask. Only valid for isochronous reception.
* Determines the tag values for which packets will be accepted.
* Use FW_CDEV_ISO_CONTEXT_MATCH_ macros to set @tags.
* @handle: Isochronous context handle within which to transmit or receive
*/
struct fw_cdev_start_iso { struct fw_cdev_start_iso {
__s32 cycle; __s32 cycle;
__u32 sync; __u32 sync;
...@@ -224,6 +451,10 @@ struct fw_cdev_start_iso { ...@@ -224,6 +451,10 @@ struct fw_cdev_start_iso {
__u32 handle; __u32 handle;
}; };
/**
* struct fw_cdev_stop_iso - Stop an isochronous transmission or reception
* @handle: Handle of isochronous context to stop
*/
struct fw_cdev_stop_iso { struct fw_cdev_stop_iso {
__u32 handle; __u32 handle;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment