X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Ffirewire%2Ffw-sbp2.c;h=16e942f72e48156cce7f603db8d5010df6fe13de;hb=8a8cea2734808522f02941ea16125810ee42c9c7;hp=c6fd7d353685c8a6bf11754330b35d7a7de3cb29;hpb=ad85274fb7f1b3c8c03f6f516dc6196a19ea4296;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index c6fd7d3..16e942f 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -207,7 +207,6 @@ struct sbp2_command_orb { struct sbp2_pointer page_table[SG_ALL]; dma_addr_t page_table_bus; - dma_addr_t request_buffer_bus; }; /* @@ -279,7 +278,7 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request, unsigned long flags; if (tcode != TCODE_WRITE_BLOCK_REQUEST || - length == 0 || length > sizeof status) { + length == 0 || length > sizeof(status)) { fw_send_response(card, request, RCODE_TYPE_ERROR); return; } @@ -340,7 +339,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit, orb->pointer.high = 0; orb->pointer.low = orb->request_bus; - fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof orb->pointer); + fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof(orb->pointer)); spin_lock_irqsave(&device->card->lock, flags); list_add_tail(&orb->link, &sd->orb_list); @@ -349,7 +348,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit, fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST, node_id, generation, device->node->max_speed, offset, - &orb->pointer, sizeof orb->pointer, + &orb->pointer, sizeof(orb->pointer), complete_transaction, orb); } @@ -386,7 +385,7 @@ complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) (struct sbp2_management_orb *)base_orb; if (status) - memcpy(&orb->status, status, sizeof *status); + memcpy(&orb->status, status, sizeof(*status)); complete(&orb->done); } @@ -399,7 +398,7 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, struct sbp2_management_orb *orb; int retval = -ENOMEM; - orb = kzalloc(sizeof *orb, GFP_ATOMIC); + orb = kzalloc(sizeof(*orb), GFP_ATOMIC); if (orb == NULL) return -ENOMEM; @@ -409,13 +408,13 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, */ orb->base.request_bus = dma_map_single(device->card->device, &orb->request, - sizeof orb->request, DMA_TO_DEVICE); + 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); + sizeof(orb->response), DMA_FROM_DEVICE); if (dma_mapping_error(orb->response_bus)) goto out; @@ -427,7 +426,7 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, MANAGEMENT_ORB_FUNCTION(function) | MANAGEMENT_ORB_LUN(lun); orb->request.length = - MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof orb->response); + MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response)); orb->request.status_fifo.high = sd->address_handler.offset >> 32; orb->request.status_fifo.low = sd->address_handler.offset; @@ -443,7 +442,7 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, MANAGEMENT_ORB_RECONNECT(0); } - fw_memcpy_to_be32(&orb->request, &orb->request, sizeof orb->request); + fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request)); init_completion(&orb->done); orb->base.callback = complete_management_orb; @@ -478,13 +477,13 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, retval = 0; out: dma_unmap_single(device->card->device, orb->base.request_bus, - sizeof orb->request, DMA_TO_DEVICE); + sizeof(orb->request), DMA_TO_DEVICE); dma_unmap_single(device->card->device, orb->response_bus, - sizeof orb->response, DMA_FROM_DEVICE); + sizeof(orb->response), DMA_FROM_DEVICE); if (response) fw_memcpy_from_be32(response, - orb->response, sizeof orb->response); + orb->response, sizeof(orb->response)); kfree(orb); return retval; @@ -506,14 +505,14 @@ static int sbp2_agent_reset(struct fw_unit *unit) struct fw_transaction *t; static u32 zero; - t = kzalloc(sizeof *t, GFP_ATOMIC); + t = kzalloc(sizeof(*t), GFP_ATOMIC); if (t == NULL) return -ENOMEM; fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, sd->node_id, sd->generation, SCODE_400, sd->command_block_agent_address + SBP2_AGENT_RESET, - &zero, sizeof zero, complete_agent_reset_write, t); + &zero, sizeof(zero), complete_agent_reset_write, t); return 0; } @@ -870,7 +869,7 @@ 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); + sizeof(orb->request), DMA_TO_DEVICE); if (orb->cmd->use_sg > 0) { sg = (struct scatterlist *)orb->cmd->request_buffer; @@ -880,19 +879,14 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) 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_bus), DMA_TO_DEVICE); orb->cmd->result = result; orb->done(orb->cmd); kfree(orb); } -static void sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) +static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) { struct sbp2_device *sd = (struct sbp2_device *)orb->cmd->device->host->hostdata; @@ -906,6 +900,8 @@ static void sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) sg = (struct scatterlist *)orb->cmd->request_buffer; count = dma_map_sg(device->card->device, sg, orb->cmd->use_sg, orb->cmd->sc_data_direction); + if (count == 0) + goto fail; /* * Handle the special case where there is only one element in @@ -919,12 +915,15 @@ static void sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) orb->request.data_descriptor.low = sg_dma_address(sg); orb->request.misc |= COMMAND_ORB_DATA_SIZE(sg_dma_len(sg)); - return; + return 0; } /* * Convert the scatterlist to an sbp2 page table. If any - * scatterlist entries are too big for sbp2 we split the as we go. + * scatterlist entries are too big for sbp2, we split them as we + * go. Even if we ask the block I/O layer to not give us sg + * elements larger than 65535 bytes, some IOMMUs may merge sg elements + * during DMA mapping, and Linux currently doesn't prevent this. */ for (i = 0, j = 0; i < count; i++) { sg_len = sg_dma_len(sg + i); @@ -939,7 +938,7 @@ static void sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) } } - size = sizeof orb->page_table[0] * j; + size = sizeof(orb->page_table[0]) * j; /* * The data_descriptor pointer is the one case where we need @@ -952,6 +951,8 @@ static void sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) 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 |= @@ -959,29 +960,14 @@ static void sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) COMMAND_ORB_DATA_SIZE(j); fw_memcpy_to_be32(orb->page_table, orb->page_table, size); -} -static void sbp2_command_orb_map_buffer(struct sbp2_command_orb *orb) -{ - struct sbp2_device *sd = - (struct sbp2_device *)orb->cmd->device->host->hostdata; - struct fw_unit *unit = sd->unit; - struct fw_device *device = fw_device(unit->device.parent); - - /* - * As for map_scatterlist, we need to fill in the high bits of - * the data_descriptor pointer. - */ + return 0; - orb->request_buffer_bus = - dma_map_single(device->card->device, - orb->cmd->request_buffer, - orb->cmd->request_bufflen, - orb->cmd->sc_data_direction); - orb->request.data_descriptor.high = sd->address_high; - orb->request.data_descriptor.low = orb->request_buffer_bus; - orb->request.misc |= - COMMAND_ORB_DATA_SIZE(orb->cmd->request_bufflen); + fail_page_table: + dma_unmap_sg(device->card->device, sg, orb->cmd->use_sg, + orb->cmd->sc_data_direction); + fail: + return -ENOMEM; } /* SCSI stack integration */ @@ -999,11 +985,13 @@ 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"); - goto fail_alloc; + fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n"); + cmd->result = DID_ERROR << 16; + done(cmd); + return 0; } - orb = kzalloc(sizeof *orb, GFP_ATOMIC); + orb = kzalloc(sizeof(*orb), GFP_ATOMIC); if (orb == NULL) { fw_notify("failed to alloc orb\n"); goto fail_alloc; @@ -1013,7 +1001,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) orb->base.rcode = -1; orb->base.request_bus = dma_map_single(device->card->device, &orb->request, - sizeof orb->request, DMA_TO_DEVICE); + sizeof(orb->request), DMA_TO_DEVICE); if (dma_mapping_error(orb->base.request_bus)) goto fail_mapping; @@ -1041,24 +1029,13 @@ 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); - } else if (cmd->request_bufflen > SBP2_MAX_SG_ELEMENT_LENGTH) { - /* - * FIXME: Need to split this into a sg list... but - * could we get the scsi or blk layer to do that by - * reporting our max supported block size? - */ - fw_error("command > 64k\n"); - goto fail_bufflen; - } else if (cmd->request_bufflen > 0) { - sbp2_command_orb_map_buffer(orb); - } + if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0) + goto fail_map_payload; - fw_memcpy_to_be32(&orb->request, &orb->request, sizeof orb->request); + fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request)); memset(orb->request.command_block, - 0, sizeof orb->request.command_block); + 0, sizeof(orb->request.command_block)); memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd)); orb->base.callback = complete_command_orb; @@ -1068,15 +1045,13 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) return 0; - fail_bufflen: + fail_map_payload: dma_unmap_single(device->card->device, orb->base.request_bus, - sizeof orb->request, DMA_TO_DEVICE); + sizeof(orb->request), DMA_TO_DEVICE); fail_mapping: kfree(orb); fail_alloc: - cmd->result = DID_ERROR << 16; - done(cmd); - return 0; + return SCSI_MLQUEUE_HOST_BUSY; } static int sbp2_scsi_slave_alloc(struct scsi_device *sdev) @@ -1127,6 +1102,58 @@ static int sbp2_scsi_abort(struct scsi_cmnd *cmd) return SUCCESS; } +/* + * Format of /sys/bus/scsi/devices/.../ieee1394_id: + * u64 EUI-64 : u24 directory_ID : u16 LUN (all printed in hexadecimal) + * + * This is the concatenation of target port identifier and logical unit + * identifier as per SAM-2...SAM-4 annex A. + */ +static ssize_t +sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + struct sbp2_device *sd; + struct fw_unit *unit; + struct fw_device *device; + u32 directory_id; + struct fw_csr_iterator ci; + int key, value, lun; + + if (!sdev) + return 0; + sd = (struct sbp2_device *)sdev->host->hostdata; + unit = sd->unit; + device = fw_device(unit->device.parent); + + /* implicit directory ID */ + directory_id = ((unit->directory - device->config_rom) * 4 + + CSR_CONFIG_ROM) & 0xffffff; + + /* explicit directory ID, overrides implicit ID if present */ + fw_csr_iterator_init(&ci, unit->directory); + while (fw_csr_iterator_next(&ci, &key, &value)) + if (key == CSR_DIRECTORY_ID) { + directory_id = value; + break; + } + + /* FIXME: Make this work for multi-lun devices. */ + lun = 0; + + return sprintf(buf, "%08x%08x:%06x:%04x\n", + device->config_rom[3], device->config_rom[4], + directory_id, lun); +} + +static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL); + +static struct device_attribute *sbp2_scsi_sysfs_attrs[] = { + &dev_attr_ieee1394_id, + NULL +}; + static struct scsi_host_template scsi_driver_template = { .module = THIS_MODULE, .name = "SBP-2 IEEE-1394", @@ -1140,6 +1167,7 @@ static struct scsi_host_template scsi_driver_template = { .use_clustering = ENABLE_CLUSTERING, .cmd_per_lun = 1, .can_queue = 1, + .sdev_attrs = sbp2_scsi_sysfs_attrs, }; MODULE_AUTHOR("Kristian Hoegsberg ");