X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Fqlogicpti.c;h=4a1cf6377f6c89b7a654bf3c38e9e2ae8b1bcc4f;hb=cd86f420614c1a2dea9c21d7f4f1acb5ec2465b2;hp=594887205b0fe7876a3fea97493a89f9402d9fb9;hpb=644b55ce889edd37d6406df26e2d96d7a7390749;p=linux-2.6-omap-h63xx.git diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 594887205b0..4a1cf6377f6 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -310,8 +310,6 @@ static inline void qlogicpti_set_hostdev_defaults(struct qlogicpti *qpti) } qpti->dev_param[i].device_enable = 1; } - /* this is very important to set! */ - qpti->sbits = 1 << qpti->scsi_id; } static int qlogicpti_reset_hardware(struct Scsi_Host *host) @@ -653,7 +651,7 @@ static int qlogicpti_verify_tmon(struct qlogicpti *qpti) static irqreturn_t qpti_intr(int irq, void *dev_id); -static void __init qpti_chain_add(struct qlogicpti *qpti) +static void __devinit qpti_chain_add(struct qlogicpti *qpti) { spin_lock_irq(&qptichain_lock); if (qptichain != NULL) { @@ -669,7 +667,7 @@ static void __init qpti_chain_add(struct qlogicpti *qpti) spin_unlock_irq(&qptichain_lock); } -static void __init qpti_chain_del(struct qlogicpti *qpti) +static void __devexit qpti_chain_del(struct qlogicpti *qpti) { spin_lock_irq(&qptichain_lock); if (qptichain == qpti) { @@ -684,7 +682,7 @@ static void __init qpti_chain_del(struct qlogicpti *qpti) spin_unlock_irq(&qptichain_lock); } -static int __init qpti_map_regs(struct qlogicpti *qpti) +static int __devinit qpti_map_regs(struct qlogicpti *qpti) { struct sbus_dev *sdev = qpti->sdev; @@ -707,7 +705,7 @@ static int __init qpti_map_regs(struct qlogicpti *qpti) return 0; } -static int __init qpti_register_irq(struct qlogicpti *qpti) +static int __devinit qpti_register_irq(struct qlogicpti *qpti) { struct sbus_dev *sdev = qpti->sdev; @@ -732,7 +730,7 @@ fail: return -1; } -static void __init qpti_get_scsi_id(struct qlogicpti *qpti) +static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) { qpti->scsi_id = prom_getintdefault(qpti->prom_node, "initiator-id", @@ -785,7 +783,7 @@ static void qpti_get_clock(struct qlogicpti *qpti) /* The request and response queues must each be aligned * on a page boundary. */ -static int __init qpti_map_queues(struct qlogicpti *qpti) +static int __devinit qpti_map_queues(struct qlogicpti *qpti) { struct sbus_dev *sdev = qpti->sdev; @@ -870,14 +868,15 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd, struct qlogicpti *qpti, u_int in_ptr, u_int out_ptr) { struct dataseg *ds; - struct scatterlist *sg; + struct scatterlist *sg, *s; int i, n; - if (Cmnd->use_sg) { + if (scsi_bufflen(Cmnd)) { int sg_count; - sg = (struct scatterlist *) Cmnd->request_buffer; - sg_count = sbus_map_sg(qpti->sdev, sg, Cmnd->use_sg, Cmnd->sc_data_direction); + sg = scsi_sglist(Cmnd); + sg_count = sbus_map_sg(qpti->sdev, sg, scsi_sg_count(Cmnd), + Cmnd->sc_data_direction); ds = cmd->dataseg; cmd->segment_cnt = sg_count; @@ -886,11 +885,12 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd, n = sg_count; if (n > 4) n = 4; - for (i = 0; i < n; i++, sg++) { - ds[i].d_base = sg_dma_address(sg); - ds[i].d_count = sg_dma_len(sg); + for_each_sg(sg, s, n, i) { + ds[i].d_base = sg_dma_address(s); + ds[i].d_count = sg_dma_len(s); } sg_count -= 4; + sg = s; while (sg_count > 0) { struct Continuation_Entry *cont; @@ -909,22 +909,12 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd, n = sg_count; if (n > 7) n = 7; - for (i = 0; i < n; i++, sg++) { - ds[i].d_base = sg_dma_address(sg); - ds[i].d_count = sg_dma_len(sg); + for_each_sg(sg, s, n, i) { + ds[i].d_base = sg_dma_address(s); + ds[i].d_count = sg_dma_len(s); } sg_count -= n; } - } else if (Cmnd->request_bufflen) { - Cmnd->SCp.ptr = (char *)(unsigned long) - sbus_map_single(qpti->sdev, - Cmnd->request_buffer, - Cmnd->request_bufflen, - Cmnd->sc_data_direction); - - cmd->dataseg[0].d_base = (u32) ((unsigned long)Cmnd->SCp.ptr); - cmd->dataseg[0].d_count = Cmnd->request_bufflen; - cmd->segment_cnt = 1; } else { cmd->dataseg[0].d_base = 0; cmd->dataseg[0].d_count = 0; @@ -951,153 +941,35 @@ static inline void update_can_queue(struct Scsi_Host *host, u_int in_ptr, u_int host->sg_tablesize = QLOGICPTI_MAX_SG(num_free); } -static unsigned int scsi_rbuf_get(struct scsi_cmnd *cmd, unsigned char **buf_out) +static int qlogicpti_slave_configure(struct scsi_device *sdev) { - unsigned char *buf; - unsigned int buflen; - - if (cmd->use_sg) { - struct scatterlist *sg; + struct qlogicpti *qpti = shost_priv(sdev->host); + int tgt = sdev->id; + u_short param[6]; - sg = (struct scatterlist *) cmd->request_buffer; - buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; - buflen = sg->length; + /* tags handled in midlayer */ + /* enable sync mode? */ + if (sdev->sdtr) { + qpti->dev_param[tgt].device_flags |= 0x10; } else { - buf = cmd->request_buffer; - buflen = cmd->request_bufflen; - } - - *buf_out = buf; - return buflen; -} - -static void scsi_rbuf_put(struct scsi_cmnd *cmd, unsigned char *buf) -{ - if (cmd->use_sg) { - struct scatterlist *sg; - - sg = (struct scatterlist *) cmd->request_buffer; - kunmap_atomic(buf - sg->offset, KM_IRQ0); - } -} - -/* - * Until we scan the entire bus with inquiries, go throught this fella... - */ -static void ourdone(struct scsi_cmnd *Cmnd) -{ - struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata; - int tgt = Cmnd->device->id; - void (*done) (struct scsi_cmnd *); - - /* This grot added by DaveM, blame him for ugliness. - * The issue is that in the 2.3.x driver we use the - * host_scribble portion of the scsi command as a - * completion linked list at interrupt service time, - * so we have to store the done function pointer elsewhere. - */ - done = (void (*)(struct scsi_cmnd *)) - (((unsigned long) Cmnd->SCp.Message) -#ifdef __sparc_v9__ - | ((unsigned long) Cmnd->SCp.Status << 32UL) -#endif - ); - - if ((qpti->sbits & (1 << tgt)) == 0) { - int ok = host_byte(Cmnd->result) == DID_OK; - if (Cmnd->cmnd[0] == 0x12 && ok) { - unsigned char *iqd; - unsigned int iqd_len; - - iqd_len = scsi_rbuf_get(Cmnd, &iqd); - - /* tags handled in midlayer */ - /* enable sync mode? */ - if (iqd[7] & 0x10) { - qpti->dev_param[tgt].device_flags |= 0x10; - } else { - qpti->dev_param[tgt].synchronous_offset = 0; - qpti->dev_param[tgt].synchronous_period = 0; - } - /* are we wide capable? */ - if (iqd[7] & 0x20) { - qpti->dev_param[tgt].device_flags |= 0x20; - } - - scsi_rbuf_put(Cmnd, iqd); - - qpti->sbits |= (1 << tgt); - } else if (!ok) { - qpti->sbits |= (1 << tgt); - } + qpti->dev_param[tgt].synchronous_offset = 0; + qpti->dev_param[tgt].synchronous_period = 0; } - done(Cmnd); -} - -static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct scsi_cmnd *)); - -static int qlogicpti_queuecommand_slow(struct scsi_cmnd *Cmnd, - void (*done)(struct scsi_cmnd *)) -{ - struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata; - - /* - * done checking this host adapter? - * If not, then rewrite the command - * to finish through ourdone so we - * can peek at Inquiry data results. - */ - if (qpti->sbits && qpti->sbits != 0xffff) { - /* See above about in ourdone this ugliness... */ - Cmnd->SCp.Message = ((unsigned long)done) & 0xffffffff; -#ifdef CONFIG_SPARC64 - Cmnd->SCp.Status = ((unsigned long)done >> 32UL) & 0xffffffff; -#endif - return qlogicpti_queuecommand(Cmnd, ourdone); - } - - /* - * We've peeked at all targets for this bus- time - * to set parameters for devices for real now. - */ - if (qpti->sbits == 0xffff) { - int i; - for(i = 0; i < MAX_TARGETS; i++) { - u_short param[6]; - param[0] = MBOX_SET_TARGET_PARAMS; - param[1] = (i << 8); - param[2] = (qpti->dev_param[i].device_flags << 8); - if (qpti->dev_param[i].device_flags & 0x10) { - param[3] = (qpti->dev_param[i].synchronous_offset << 8) | - qpti->dev_param[i].synchronous_period; - } else { - param[3] = 0; - } - (void) qlogicpti_mbox_command(qpti, param, 0); - } - /* - * set to zero so any traverse through ourdone - * doesn't start the whole process again, - */ - qpti->sbits = 0; - } - - /* check to see if we're done with all adapters... */ - for (qpti = qptichain; qpti != NULL; qpti = qpti->next) { - if (qpti->sbits) { - break; - } + /* are we wide capable? */ + if (sdev->wdtr) + qpti->dev_param[tgt].device_flags |= 0x20; + + param[0] = MBOX_SET_TARGET_PARAMS; + param[1] = (tgt << 8); + param[2] = (qpti->dev_param[tgt].device_flags << 8); + if (qpti->dev_param[tgt].device_flags & 0x10) { + param[3] = (qpti->dev_param[tgt].synchronous_offset << 8) | + qpti->dev_param[tgt].synchronous_period; + } else { + param[3] = 0; } - - /* - * if we hit the end of the chain w/o finding adapters still - * capability-configuring, then we're done with all adapters - * and can rock on.. - */ - if (qpti == NULL) - Cmnd->device->host->hostt->queuecommand = qlogicpti_queuecommand; - - return qlogicpti_queuecommand(Cmnd, done); + qlogicpti_mbox_command(qpti, param, 0); + return 0; } /* @@ -1270,7 +1142,7 @@ static struct scsi_cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti) if (sts->state_flags & SF_GOT_SENSE) memcpy(Cmnd->sense_buffer, sts->req_sense_data, - sizeof(Cmnd->sense_buffer)); + SCSI_SENSE_BUFFERSIZE); if (sts->hdr.entry_type == ENTRY_STATUS) Cmnd->result = @@ -1278,17 +1150,11 @@ static struct scsi_cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti) else Cmnd->result = DID_ERROR << 16; - if (Cmnd->use_sg) { + if (scsi_bufflen(Cmnd)) sbus_unmap_sg(qpti->sdev, - (struct scatterlist *)Cmnd->request_buffer, - Cmnd->use_sg, + scsi_sglist(Cmnd), scsi_sg_count(Cmnd), Cmnd->sc_data_direction); - } else if (Cmnd->request_bufflen) { - sbus_unmap_single(qpti->sdev, - (__u32)((unsigned long)Cmnd->SCp.ptr), - Cmnd->request_bufflen, - Cmnd->sc_data_direction); - } + qpti->cmd_count[Cmnd->device->id]--; sbus_writew(out_ptr, qpti->qregs + MBOX5); Cmnd->host_scribble = (unsigned char *) done_queue; @@ -1390,7 +1256,8 @@ static struct scsi_host_template qpti_template = { .module = THIS_MODULE, .name = "qlogicpti", .info = qlogicpti_info, - .queuecommand = qlogicpti_queuecommand_slow, + .queuecommand = qlogicpti_queuecommand, + .slave_configure = qlogicpti_slave_configure, .eh_abort_handler = qlogicpti_abort, .eh_bus_reset_handler = qlogicpti_reset, .can_queue = QLOGICPTI_REQ_QUEUE_LEN,