diff options
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/Kconfig | 65 | ||||
-rw-r--r-- | drivers/firewire/fw-card.c | 7 | ||||
-rw-r--r-- | drivers/firewire/fw-cdev.c | 2 | ||||
-rw-r--r-- | drivers/firewire/fw-device.c | 38 | ||||
-rw-r--r-- | drivers/firewire/fw-device.h | 1 | ||||
-rw-r--r-- | drivers/firewire/fw-ohci.c | 15 | ||||
-rw-r--r-- | drivers/firewire/fw-sbp2.c | 133 | ||||
-rw-r--r-- | drivers/firewire/fw-topology.c | 66 | ||||
-rw-r--r-- | drivers/firewire/fw-topology.h | 25 | ||||
-rw-r--r-- | drivers/firewire/fw-transaction.c | 9 | ||||
-rw-r--r-- | drivers/firewire/fw-transaction.h | 7 |
11 files changed, 204 insertions, 164 deletions
diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig index 396dade731f..d011a76f8e7 100644 --- a/drivers/firewire/Kconfig +++ b/drivers/firewire/Kconfig @@ -4,27 +4,44 @@ comment "An alternative FireWire stack is available with EXPERIMENTAL=y" depends on EXPERIMENTAL=n config FIREWIRE - tristate "IEEE 1394 (FireWire) support (JUJU alternative stack, experimental)" + tristate "IEEE 1394 (FireWire) support - alternative stack, EXPERIMENTAL" depends on EXPERIMENTAL select CRC_ITU_T help - IEEE 1394 describes a high performance serial bus, which is also - known as FireWire(tm) or i.Link(tm) and is used for connecting all - sorts of devices (most notably digital video cameras) to your - computer. - - If you have FireWire hardware and want to use it, say Y here. This - is the core support only, you will also need to select a driver for - your IEEE 1394 adapter. - - To compile this driver as a module, say M here: the module will be - called firewire-core. - - This is the "JUJU" FireWire stack, an alternative implementation + This is the "Juju" FireWire stack, a new alternative implementation designed for robustness and simplicity. You can build either this stack, or the classic stack (the ieee1394 driver, ohci1394 etc.) or both. + To compile this driver as a module, say M here: the module will be + called firewire-core. It functionally replaces ieee1394, raw1394, + and video1394. + + NOTE: + + You should only build ONE of the stacks, unless you REALLY know what + you are doing. If you install both, you should configure them only as + modules rather than link them statically, and you should blacklist one + of the concurrent low-level drivers in /etc/modprobe.conf. Add either + + blacklist firewire-ohci + or + blacklist ohci1394 + + there depending on which driver you DON'T want to have auto-loaded. + You can optionally do the same with the other IEEE 1394/ FireWire + drivers. + + If you have an old modprobe which doesn't implement the blacklist + directive, use either + + install firewire-ohci /bin/true + or + install ohci1394 /bin/true + + and so on, depending on which modules you DON't want to have + auto-loaded. + config FIREWIRE_OHCI tristate "Support for OHCI FireWire host controllers" depends on PCI && FIREWIRE @@ -34,11 +51,13 @@ config FIREWIRE_OHCI is the only chipset in use, so say Y here. To compile this driver as a module, say M here: The module will be - called firewire-ohci. + called firewire-ohci. It replaces ohci1394 of the classic IEEE 1394 + stack. + + NOTE: - If you also build ohci1394 of the classic IEEE 1394 driver stack, - blacklist either ohci1394 or firewire-ohci to let hotplug load the - desired driver. + If you also build ohci1394 of the classic stack, blacklist either + ohci1394 or firewire-ohci to let hotplug load only the desired driver. config FIREWIRE_SBP2 tristate "Support for storage devices (SBP-2 protocol driver)" @@ -50,12 +69,14 @@ config FIREWIRE_SBP2 like scanners. To compile this driver as a module, say M here: The module will be - called firewire-sbp2. + called firewire-sbp2. It replaces sbp2 of the classic IEEE 1394 + stack. You should also enable support for disks, CD-ROMs, etc. in the SCSI configuration section. - If you also build sbp2 of the classic IEEE 1394 driver stack, - blacklist either sbp2 or firewire-sbp2 to let hotplug load the - desired driver. + NOTE: + + If you also build sbp2 of the classic stack, blacklist either sbp2 + or firewire-sbp2 to let hotplug load only the desired driver. diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 9eb1edacd82..0aeab3218bb 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -336,8 +336,11 @@ fw_card_bm_work(struct work_struct *work) } 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)) gap_count = gap_count_table[card->root_node->max_hops]; else diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index dbb76427d52..75388641a7d 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -397,7 +397,7 @@ static int ioctl_send_request(struct client *client, void *buffer) request->tcode & 0x1f, device->node->node_id, request->generation, - device->node->max_speed, + device->max_speed, request->offset, response->response.data, request->length, complete_transaction, response); diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index c1ce465d971..2b658634163 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -401,8 +401,7 @@ static int read_rom(struct fw_device *device, int index, u32 * data) offset = 0xfffff0000400ULL + index * 4; fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST, - device->node_id, - device->generation, SCODE_100, + device->node_id, device->generation, device->max_speed, offset, NULL, 4, complete_transaction, &callback_data); wait_for_completion(&callback_data.done); @@ -418,6 +417,8 @@ static int read_bus_info_block(struct fw_device *device) u32 stack[16], sp, key; int i, end, length; + device->max_speed = SCODE_100; + /* First read the bus info block. */ for (i = 0; i < 5; i++) { if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) @@ -434,6 +435,33 @@ static int read_bus_info_block(struct fw_device *device) 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 * directory structure so we parse it using a stack of @@ -680,8 +708,10 @@ static void fw_device_init(struct work_struct *work) FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) fw_device_shutdown(&device->work.work); else - fw_notify("created new fw device %s (%d config rom retries)\n", - device->device.bus_id, device->config_rom_retries); + fw_notify("created new fw device %s " + "(%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 diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index af1723eae4b..d13e6a69707 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h @@ -40,6 +40,7 @@ struct fw_device { struct fw_node *node; int node_id; int generation; + unsigned max_speed; struct fw_card *card; struct device device; struct list_head link; diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index b72a5c1f9e6..db703758db9 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -224,6 +224,7 @@ ohci_update_phy_reg(struct fw_card *card, int addr, u32 val, old; reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); + flush_writes(ohci); msleep(2); val = reg_read(ohci, OHCI1394_PhyControl); if ((val & OHCI1394_PhyControl_ReadDone) == 0) { @@ -373,8 +374,8 @@ static void ar_context_tasklet(unsigned long data) offset = offsetof(struct ar_buffer, data); dma_unmap_single(ohci->card.device, - ab->descriptor.data_address - offset, - PAGE_SIZE, DMA_BIDIRECTIONAL); + le32_to_cpu(ab->descriptor.data_address) - offset, + PAGE_SIZE, DMA_BIDIRECTIONAL); buffer = ab; ab = ab->next; @@ -427,7 +428,7 @@ static void ar_context_run(struct ar_context *ctx) size_t offset; offset = offsetof(struct ar_buffer, data); - ab_bus = ab->descriptor.data_address - offset; + ab_bus = le32_to_cpu(ab->descriptor.data_address) - offset; reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ab_bus | 1); reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN); @@ -586,7 +587,7 @@ static void context_stop(struct context *ctx) break; fw_notify("context_stop: still active (0x%08x)\n", reg); - msleep(1); + mdelay(1); } } @@ -1934,12 +1935,12 @@ static int pci_suspend(struct pci_dev *pdev, pm_message_t state) free_irq(pdev->irq, ohci); err = pci_save_state(pdev); if (err) { - fw_error("pci_save_state failed with %d", err); + fw_error("pci_save_state failed\n"); return err; } err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); if (err) { - fw_error("pci_set_power_state failed with %d", err); + fw_error("pci_set_power_state failed\n"); return err; } @@ -1955,7 +1956,7 @@ static int pci_resume(struct pci_dev *pdev) pci_restore_state(pdev); err = pci_enable_device(pdev); if (err) { - fw_error("pci_enable_device failed with %d", err); + fw_error("pci_enable_device failed\n"); return err; } diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index a98d3915e26..fc984474162 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -30,10 +30,13 @@ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/moduleparam.h> #include <linux/mod_devicetable.h> #include <linux/device.h> #include <linux/scatterlist.h> #include <linux/dma-mapping.h> +#include <linux/blkdev.h> +#include <linux/string.h> #include <linux/timer.h> #include <scsi/scsi.h> @@ -46,6 +49,18 @@ #include "fw-topology.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... */ typedef void (*scsi_done_fn_t)(struct scsi_cmnd *); @@ -154,7 +169,7 @@ struct sbp2_orb { #define MANAGEMENT_ORB_LUN(v) ((v)) #define MANAGEMENT_ORB_FUNCTION(v) ((v) << 16) #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_NOTIFY ((1) << 31) @@ -205,9 +220,8 @@ struct sbp2_command_orb { scsi_done_fn_t done; 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 request_buffer_bus; }; /* @@ -347,8 +361,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit, spin_unlock_irqrestore(&device->card->lock, flags); fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST, - node_id, generation, - device->node->max_speed, offset, + node_id, generation, device->max_speed, offset, &orb->pointer, sizeof(orb->pointer), complete_transaction, orb); } @@ -383,7 +396,7 @@ static void complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) { struct sbp2_management_orb *orb = - (struct sbp2_management_orb *)base_orb; + container_of(base_orb, struct sbp2_management_orb, base); if (status) memcpy(&orb->status, status, sizeof(*status)); @@ -403,21 +416,11 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, if (orb == NULL) 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 = dma_map_single(device->card->device, &orb->response, sizeof(orb->response), DMA_FROM_DEVICE); if (dma_mapping_error(orb->response_bus)) - goto out; + goto fail_mapping_response; orb->request.response.high = 0; orb->request.response.low = orb->response_bus; @@ -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.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) { orb->request.misc |= - MANAGEMENT_ORB_EXCLUSIVE | + MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login) | MANAGEMENT_ORB_RECONNECT(0); } @@ -448,6 +446,12 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, init_completion(&orb->done); 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, node_id, generation, sd->management_agent_address); @@ -479,9 +483,10 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, out: dma_unmap_single(device->card->device, orb->base.request_bus, sizeof(orb->request), DMA_TO_DEVICE); + fail_mapping_request: dma_unmap_single(device->card->device, orb->response_bus, sizeof(orb->response), DMA_FROM_DEVICE); - + fail_mapping_response: if (response) fw_memcpy_from_be32(response, orb->response, sizeof(orb->response)); @@ -511,7 +516,7 @@ static int sbp2_agent_reset(struct fw_unit *unit) return -ENOMEM; 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, &zero, sizeof(zero), complete_agent_reset_write, t); @@ -521,17 +526,15 @@ static int sbp2_agent_reset(struct fw_unit *unit) static void sbp2_reconnect(struct work_struct *work); static struct scsi_host_template scsi_driver_template; -static void -release_sbp2_device(struct kref *kref) +static void release_sbp2_device(struct kref *kref) { struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref); struct Scsi_Host *host = 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_LOGOUT_REQUEST, sd->login_id, NULL); - - scsi_remove_host(host); fw_core_remove_address_handler(&sd->address_handler); fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id); put_device(&sd->unit->device); @@ -833,10 +836,10 @@ sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) static void 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_device *device = fw_device(unit->device.parent); - struct scatterlist *sg; int result; if (status != NULL) { @@ -872,20 +875,14 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) dma_unmap_single(device->card->device, orb->base.request_bus, sizeof(orb->request), DMA_TO_DEVICE); - if (orb->cmd->use_sg > 0) { - sg = (struct scatterlist *)orb->cmd->request_buffer; - dma_unmap_sg(device->card->device, sg, orb->cmd->use_sg, + if (scsi_sg_count(orb->cmd) > 0) + dma_unmap_sg(device->card->device, scsi_sglist(orb->cmd), + scsi_sg_count(orb->cmd), orb->cmd->sc_data_direction); - } if (orb->page_table_bus != 0) dma_unmap_single(device->card->device, orb->page_table_bus, - sizeof(orb->page_table_bus), 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); + sizeof(orb->page_table), DMA_TO_DEVICE); orb->cmd->result = result; orb->done(orb->cmd); @@ -900,11 +897,10 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) struct fw_device *device = fw_device(unit->device.parent); struct scatterlist *sg; int sg_len, l, i, j, count; - size_t size; dma_addr_t sg_addr; - sg = (struct scatterlist *)orb->cmd->request_buffer; - count = dma_map_sg(device->card->device, sg, orb->cmd->use_sg, + sg = scsi_sglist(orb->cmd); + count = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd), orb->cmd->sc_data_direction); if (count == 0) goto fail; @@ -935,6 +931,11 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) sg_len = sg_dma_len(sg + i); sg_addr = sg_dma_address(sg + i); 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); orb->page_table[j].low = sg_addr; orb->page_table[j].high = (l << 16); @@ -944,7 +945,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 @@ -953,24 +960,16 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) * initiator (i.e. us), but data_descriptor can refer to data * 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.low = orb->page_table_bus; orb->request.misc |= COMMAND_ORB_PAGE_TABLE_PRESENT | COMMAND_ORB_DATA_SIZE(j); - fw_memcpy_to_be32(orb->page_table, orb->page_table, size); - return 0; fail_page_table: - dma_unmap_sg(device->card->device, sg, orb->cmd->use_sg, + dma_unmap_sg(device->card->device, sg, scsi_sg_count(orb->cmd), orb->cmd->sc_data_direction); fail: return -ENOMEM; @@ -991,7 +990,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) * transfer direction not handled. */ 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; done(cmd); return 0; @@ -1005,11 +1004,6 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) /* Initialize rcode to something not RCODE_COMPLETE. */ 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->done = done; @@ -1024,8 +1018,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. */ orb->request.misc = - COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) | - COMMAND_ORB_SPEED(device->node->max_speed) | + COMMAND_ORB_MAX_PAYLOAD(device->max_speed + 7) | + COMMAND_ORB_SPEED(device->max_speed) | COMMAND_ORB_NOTIFY; if (cmd->sc_data_direction == DMA_FROM_DEVICE) @@ -1035,8 +1029,8 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) orb->request.misc |= COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA); - if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0) - goto fail_map_payload; + if (scsi_sg_count(cmd) && sbp2_command_orb_map_scatterlist(orb) < 0) + goto fail_mapping; fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request)); @@ -1045,15 +1039,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)); 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, sd->command_block_agent_address + SBP2_ORB_POINTER); return 0; - fail_map_payload: - dma_unmap_single(device->card->device, orb->base.request_bus, - sizeof(orb->request), DMA_TO_DEVICE); fail_mapping: kfree(orb); fail_alloc: @@ -1087,7 +1083,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) fw_notify("setting fix_capacity for %s\n", unit->device.bus_id); sdev->fix_capacity = 1; } - + if (sd->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) + blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512); return 0; } diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index 7aebb8ae0ef..39e5cd12aa5 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c @@ -135,17 +135,17 @@ static void update_hop_count(struct fw_node *node) int i; for (i = 0; i < node->port_count; i++) { - if (node->ports[i].node == NULL) + if (node->ports[i] == NULL) continue; - if (node->ports[i].node->max_hops > max_child_hops) - max_child_hops = node->ports[i].node->max_hops; + if (node->ports[i]->max_hops > max_child_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[0] = node->ports[i].node->max_depth; - } else if (node->ports[i].node->max_depth > depths[1]) - depths[1] = node->ports[i].node->max_depth; + depths[0] = node->ports[i]->max_depth; + } else if (node->ports[i]->max_depth > depths[1]) + depths[1] = node->ports[i]->max_depth; } node->max_depth = depths[0] + 1; @@ -172,7 +172,8 @@ static struct fw_node *build_tree(struct fw_card *card, struct list_head stack, *h; u32 *next_sid, *end, q; 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; node = NULL; @@ -182,7 +183,7 @@ static struct fw_node *build_tree(struct fw_card *card, phy_id = 0; irm_node = NULL; gap_count = SELF_ID_GAP_COUNT(*sid); - topology_type = 0; + beta_repeaters_present = false; while (sid < end) { next_sid = count_ports(sid, &port_count, &child_port_count); @@ -214,7 +215,7 @@ static struct fw_node *build_tree(struct fw_card *card, node = fw_node_create(q, port_count, card->color); if (node == NULL) { - fw_error("Out of memory while building topology."); + fw_error("Out of memory while building topology.\n"); return NULL; } @@ -224,11 +225,6 @@ static struct fw_node *build_tree(struct fw_card *card, if (SELF_ID_CONTENDER(q)) irm_node = node; - if (node->phy_speed == SCODE_BETA) - topology_type |= FW_TOPOLOGY_B; - else - topology_type |= FW_TOPOLOGY_A; - parent_count = 0; for (i = 0; i < port_count; i++) { @@ -249,12 +245,12 @@ static struct fw_node *build_tree(struct fw_card *card, break; case SELFID_PORT_CHILD: - node->ports[i].node = child; + node->ports[i] = child; /* * Fix up parent reference for this * child node. */ - child->ports[child->color].node = node; + child->ports[child->color] = node; child->color = card->color; child = fw_node(child->link.next); break; @@ -278,6 +274,10 @@ static struct fw_node *build_tree(struct fw_card *card, list_add_tail(&node->link, &stack); 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 * 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, card->root_node = node; card->irm_node = irm_node; card->gap_count = gap_count; - card->topology_type = topology_type; + card->beta_repeaters_present = beta_repeaters_present; return local_node; } @@ -321,7 +321,7 @@ for_each_fw_node(struct fw_card *card, struct fw_node *root, node->color = card->color; for (i = 0; i < node->port_count; i++) { - child = node->ports[i].node; + child = node->ports[i]; if (!child) continue; if (child->color == card->color) @@ -382,11 +382,11 @@ static void move_tree(struct fw_node *node0, struct fw_node *node1, int port) struct fw_node *tree; int i; - tree = node1->ports[port].node; - node0->ports[port].node = tree; + tree = node1->ports[port]; + node0->ports[port] = tree; for (i = 0; i < tree->port_count; i++) { - if (tree->ports[i].node == node1) { - tree->ports[i].node = node0; + if (tree->ports[i] == node1) { + tree->ports[i] = node0; break; } } @@ -437,19 +437,17 @@ update_tree(struct fw_card *card, struct fw_node *root) card->irm_node = node0; 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 * connected node for further * investigation. */ - if (node0->ports[i].node->color == card->color) + if (node0->ports[i]->color == card->color) continue; - list_add_tail(&node0->ports[i].node->link, - &list0); - list_add_tail(&node1->ports[i].node->link, - &list1); - } else if (node0->ports[i].node) { + list_add_tail(&node0->ports[i]->link, &list0); + list_add_tail(&node1->ports[i]->link, &list1); + } else if (node0->ports[i]) { /* * The nodes connected here were * unplugged; unref the lost nodes and @@ -457,10 +455,10 @@ update_tree(struct fw_card *card, struct fw_node *root) * them. */ - for_each_fw_node(card, node0->ports[i].node, + for_each_fw_node(card, node0->ports[i], report_lost_node); - node0->ports[i].node = NULL; - } else if (node1->ports[i].node) { + node0->ports[i] = NULL; + } else if (node1->ports[i]) { /* * One or more node were connected to * this port. Move the new nodes into @@ -468,7 +466,7 @@ update_tree(struct fw_card *card, struct fw_node *root) * callbacks for them. */ 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); } } diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h index 363b6cbcd0b..1b56b4ac7fb 100644 --- a/drivers/firewire/fw-topology.h +++ b/drivers/firewire/fw-topology.h @@ -20,12 +20,6 @@ #define __fw_topology_h enum { - FW_TOPOLOGY_A = 0x01, - FW_TOPOLOGY_B = 0x02, - FW_TOPOLOGY_MIXED = 0x03, -}; - -enum { FW_NODE_CREATED = 0x00, FW_NODE_UPDATED = 0x01, FW_NODE_DESTROYED = 0x02, @@ -33,21 +27,16 @@ enum { FW_NODE_LINK_OFF = 0x04, }; -struct fw_port { - struct fw_node *node; - unsigned speed : 3; /* S100, S200, ... S3200 */ -}; - struct fw_node { u16 node_id; u8 color; u8 port_count; - unsigned link_on : 1; - unsigned initiated_reset : 1; - unsigned b_path : 1; - u8 phy_speed : 3; /* As in the self ID packet. */ - u8 max_speed : 5; /* Minimum of all phy-speeds and port speeds on - * the path from the local node to this node. */ + u8 link_on : 1; + u8 initiated_reset : 1; + u8 b_path : 1; + u8 phy_speed : 2; /* As in the self ID packet. */ + u8 max_speed : 2; /* Minimum of all phy-speeds on the path from the + * local node to this node. */ u8 max_depth : 4; /* Maximum depth to any leaf node */ u8 max_hops : 4; /* Max hops in this sub tree */ atomic_t ref_count; @@ -58,7 +47,7 @@ struct fw_node { /* Upper layer specific data. */ void *data; - struct fw_port ports[0]; + struct fw_node *ports[0]; }; static inline struct fw_node * diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 80d0121463d..3ce8e2fbe15 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -605,8 +605,10 @@ fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) * check is sufficient to ensure we don't send response to * broadcast packets or posted writes. */ - if (request->ack != ACK_PENDING) + if (request->ack != ACK_PENDING) { + kfree(request); return; + } if (rcode == RCODE_COMPLETE) fw_fill_response(&request->response, request->request_header, @@ -628,11 +630,6 @@ fw_core_handle_request(struct fw_card *card, struct fw_packet *p) unsigned long flags; int tcode, destination, source; - if (p->payload_length > 2048) { - /* FIXME: send error response. */ - return; - } - if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE) return; diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index acdc3be38c6..5ceaccd1056 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -81,7 +81,6 @@ #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_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args) static inline void fw_memcpy_from_be32(void *_dst, void *_src, size_t size) @@ -124,6 +123,10 @@ typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode, size_t length, void *callback_data); +/* + * Important note: The callback must guarantee that either fw_send_response() + * or kfree() is called on the @request. + */ typedef void (*fw_address_callback_t)(struct fw_card *card, struct fw_request *request, int tcode, int destination, int source, @@ -246,7 +249,7 @@ struct fw_card { struct fw_node *irm_node; int color; int gap_count; - int topology_type; + bool beta_repeaters_present; int index; |