diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/Kconfig | 10 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_task.c | 4 | ||||
-rw-r--r-- | drivers/scsi/esp_scsi.c | 3 | ||||
-rw-r--r-- | drivers/scsi/ipr.c | 19 | ||||
-rw-r--r-- | drivers/scsi/libiscsi.c | 65 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 11 | ||||
-rw-r--r-- | drivers/scsi/megaraid.c | 8 | ||||
-rw-r--r-- | drivers/scsi/scsi_lib.c | 21 | ||||
-rw-r--r-- | drivers/scsi/scsi_netlink.c | 27 | ||||
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 9 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 84 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_spi.c | 28 |
12 files changed, 153 insertions, 136 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index de6a641..30905ce 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -388,6 +388,7 @@ config SCSI_3W_9XXX config SCSI_7000FASST tristate "7000FASST SCSI support" depends on ISA && SCSI && ISA_DMA_API + select CHECK_SIGNATURE help This driver supports the Western Digital 7000 SCSI host adapter family. Some information is in the source: @@ -409,6 +410,7 @@ config SCSI_AHA152X tristate "Adaptec AHA152X/2825 support" depends on ISA && SCSI && !64BIT select SCSI_SPI_ATTRS + select CHECK_SIGNATURE ---help--- This is a driver for the AHA-1510, AHA-1520, AHA-1522, and AHA-2825 SCSI host adapters. It also works for the AVA-1505, but the IRQ etc. @@ -616,6 +618,7 @@ config SCSI_DTC3280 tristate "DTC3180/3280 SCSI support" depends on ISA && SCSI select SCSI_SPI_ATTRS + select CHECK_SIGNATURE help This is support for DTC 3180/3280 SCSI Host Adapters. Please read the SCSI-HOWTO, available from @@ -690,6 +693,7 @@ config SCSI_EATA_PIO config SCSI_FUTURE_DOMAIN tristate "Future Domain 16xx SCSI/AHA-2920A support" depends on (ISA || PCI) && SCSI + select CHECK_SIGNATURE ---help--- This is support for Future Domain's 16-bit SCSI host adapters (TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and @@ -1358,6 +1362,7 @@ config SCSI_LPFC config SCSI_SEAGATE tristate "Seagate ST-02 and Future Domain TMC-8xx SCSI support" depends on X86 && ISA && SCSI + select CHECK_SIGNATURE ---help--- These are 8-bit SCSI controllers; the ST-01 is also supported by this driver. It is explained in section 3.9 of the SCSI-HOWTO, @@ -1431,6 +1436,7 @@ config SCSI_T128 tristate "Trantor T128/T128F/T228 SCSI support" depends on ISA && SCSI select SCSI_SPI_ATTRS + select CHECK_SIGNATURE ---help--- This is support for a SCSI host adapter. It is explained in section 3.11 of the SCSI-HOWTO, available from @@ -1595,7 +1601,7 @@ config A3000_SCSI built-in SCSI controller, say Y. Otherwise, say N. To compile this driver as a module, choose M here: the - module will be called wd33c93. + module will be called a3000. config A2091_SCSI tristate "A2091/A590 WD33C93A support" @@ -1605,7 +1611,7 @@ config A2091_SCSI say N. To compile this driver as a module, choose M here: the - module will be called wd33c93. + module will be called a2091. config GVP11_SCSI tristate "GVP Series II WD33C93A support" diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index 4c759ce..f2b23e0 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c @@ -451,7 +451,7 @@ static int asd_build_smp_ascb(struct asd_ascb *ascb, struct sas_task *task, struct scb *scb; pci_map_sg(asd_ha->pcidev, &task->smp_task.smp_req, 1, - PCI_DMA_FROMDEVICE); + PCI_DMA_TODEVICE); pci_map_sg(asd_ha->pcidev, &task->smp_task.smp_resp, 1, PCI_DMA_FROMDEVICE); @@ -486,7 +486,7 @@ static void asd_unbuild_smp_ascb(struct asd_ascb *a) BUG_ON(!task); pci_unmap_sg(a->ha->pcidev, &task->smp_task.smp_req, 1, - PCI_DMA_FROMDEVICE); + PCI_DMA_TODEVICE); pci_unmap_sg(a->ha->pcidev, &task->smp_task.smp_resp, 1, PCI_DMA_FROMDEVICE); } diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c index f346fd1..4ed3a52 100644 --- a/drivers/scsi/esp_scsi.c +++ b/drivers/scsi/esp_scsi.c @@ -2314,6 +2314,7 @@ int scsi_esp_register(struct esp *esp, struct device *dev) esp->host->transportt = esp_transport_template; esp->host->max_lun = ESP_MAX_LUN; esp->host->cmd_per_lun = 2; + esp->host->unique_id = instance; esp_set_clock_params(esp); @@ -2337,7 +2338,7 @@ int scsi_esp_register(struct esp *esp, struct device *dev) if (err) return err; - esp->host->unique_id = instance++; + instance++; scsi_scan_host(esp->host); diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index f142eaf..b41dfb5 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -3829,18 +3829,18 @@ static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg, /** * ipr_sata_reset - Reset the SATA port - * @ap: SATA port to reset + * @link: SATA link to reset * @classes: class of the attached device * - * This function issues a SATA phy reset to the affected ATA port. + * This function issues a SATA phy reset to the affected ATA link. * * Return value: * 0 on success / non-zero on failure **/ -static int ipr_sata_reset(struct ata_port *ap, unsigned int *classes, +static int ipr_sata_reset(struct ata_link *link, unsigned int *classes, unsigned long deadline) { - struct ipr_sata_port *sata_port = ap->private_data; + struct ipr_sata_port *sata_port = link->ap->private_data; struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg; struct ipr_resource_entry *res; unsigned long lock_flags = 0; @@ -4981,22 +4981,22 @@ static void ipr_ata_phy_reset(struct ata_port *ap) rc = ipr_device_reset(ioa_cfg, res); if (rc) { - ap->ops->port_disable(ap); + ata_port_disable(ap); goto out_unlock; } switch(res->cfgte.proto) { case IPR_PROTO_SATA: case IPR_PROTO_SAS_STP: - ap->device[0].class = ATA_DEV_ATA; + ap->link.device[0].class = ATA_DEV_ATA; break; case IPR_PROTO_SATA_ATAPI: case IPR_PROTO_SAS_STP_ATAPI: - ap->device[0].class = ATA_DEV_ATAPI; + ap->link.device[0].class = ATA_DEV_ATAPI; break; default: - ap->device[0].class = ATA_DEV_UNKNOWN; - ap->ops->port_disable(ap); + ap->link.device[0].class = ATA_DEV_UNKNOWN; + ata_port_disable(ap); break; }; @@ -5262,7 +5262,6 @@ static u8 ipr_ata_check_altstatus(struct ata_port *ap) } static struct ata_port_operations ipr_sata_ops = { - .port_disable = ata_port_disable, .check_status = ipr_ata_check_status, .check_altstatus = ipr_ata_check_altstatus, .dev_select = ata_noop_dev_select, diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 5606d1e..efceed4 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -737,12 +737,19 @@ check_mgmt: */ conn->ctask = list_entry(conn->xmitqueue.next, struct iscsi_cmd_task, running); - if (conn->ctask->state == ISCSI_TASK_PENDING) { + switch (conn->ctask->state) { + case ISCSI_TASK_ABORTING: + break; + case ISCSI_TASK_PENDING: iscsi_prep_scsi_cmd_pdu(conn->ctask); conn->session->tt->init_cmd_task(conn->ctask); + /* fall through */ + default: + conn->ctask->state = ISCSI_TASK_RUNNING; + break; } - conn->ctask->state = ISCSI_TASK_RUNNING; list_move_tail(conn->xmitqueue.next, &conn->run_list); + rc = iscsi_xmit_ctask(conn); if (rc) goto again; @@ -1049,7 +1056,9 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, ctask->mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); if (!ctask->mtask) { + spin_unlock_bh(&session->lock); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + spin_lock_bh(&session->lock) debug_scsi("abort sent failure [itt 0x%x]\n", ctask->itt); return -EPERM; } @@ -1066,6 +1075,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt); } spin_unlock_bh(&session->lock); + mutex_unlock(&session->eh_mutex); scsi_queue_work(session->host, &conn->xmitwork); /* @@ -1083,6 +1093,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, if (signal_pending(current)) flush_signals(current); del_timer_sync(&conn->tmabort_timer); + mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); return 0; } @@ -1158,31 +1169,45 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, __iscsi_put_ctask(ctask); } +static void iscsi_suspend_tx(struct iscsi_conn *conn) +{ + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + scsi_flush_work(conn->session->host); +} + +static void iscsi_start_tx(struct iscsi_conn *conn) +{ + clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + scsi_queue_work(conn->session->host, &conn->xmitwork); +} + int iscsi_eh_abort(struct scsi_cmnd *sc) { + struct Scsi_Host *host = sc->device->host; + struct iscsi_session *session = iscsi_hostdata(host->hostdata); struct iscsi_cmd_task *ctask; struct iscsi_conn *conn; - struct iscsi_session *session; int rc; + mutex_lock(&session->eh_mutex); + spin_lock_bh(&session->lock); /* * if session was ISCSI_STATE_IN_RECOVERY then we may not have * got the command. */ if (!sc->SCp.ptr) { debug_scsi("sc never reached iscsi layer or it completed.\n"); + spin_unlock_bh(&session->lock); + mutex_unlock(&session->eh_mutex); return SUCCESS; } ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; conn = ctask->conn; - session = conn->session; conn->eh_abort_cnt++; debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); - spin_lock_bh(&session->lock); - /* * If we are not logged in or we have started a new session * then let the host reset code handle this @@ -1219,6 +1244,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) switch (conn->tmabort_state) { case TMABORT_SUCCESS: spin_unlock_bh(&session->lock); + iscsi_suspend_tx(conn); /* * clean up task if aborted. grab the recv lock as a writer */ @@ -1227,11 +1253,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) fail_command(conn, ctask, DID_ABORT << 16); spin_unlock(&session->lock); write_unlock_bh(conn->recv_lock); - /* - * make sure xmit thread is not still touching the - * ctask/scsi_cmnd - */ - scsi_flush_work(session->host); + iscsi_start_tx(conn); goto success_unlocked; case TMABORT_NOT_FOUND: if (!ctask->sc) { @@ -1251,12 +1273,14 @@ success: spin_unlock_bh(&session->lock); success_unlocked: debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + mutex_unlock(&session->eh_mutex); return SUCCESS; failed: spin_unlock_bh(&session->lock); failed_unlocked: debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + mutex_unlock(&session->eh_mutex); return FAILED; } EXPORT_SYMBOL_GPL(iscsi_eh_abort); @@ -1403,6 +1427,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, session->max_cmdsn = initial_cmdsn + 1; session->max_r2t = 1; session->tt = iscsit; + mutex_init(&session->eh_mutex); /* initialize SCSI PDU commands pool */ if (iscsi_pool_init(&session->cmdpool, session->cmds_max, @@ -1736,9 +1761,22 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, { int old_stop_stage; + mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); if (conn->stop_stage == STOP_CONN_TERM) { spin_unlock_bh(&session->lock); + mutex_unlock(&session->eh_mutex); + return; + } + + /* + * The LLD either freed/unset the lock on us, or userspace called + * stop but did not create a proper connection (connection was never + * bound or it was unbound then stop was called). + */ + if (!conn->recv_lock) { + spin_unlock_bh(&session->lock); + mutex_unlock(&session->eh_mutex); return; } @@ -1755,9 +1793,9 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, old_stop_stage = conn->stop_stage; conn->stop_stage = flag; conn->c_stage = ISCSI_CONN_STOPPED; - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); spin_unlock_bh(&session->lock); - scsi_flush_work(session->host); + + iscsi_suspend_tx(conn); write_lock_bh(conn->recv_lock); set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); @@ -1786,6 +1824,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, fail_all_commands(conn); flush_control_queues(session, conn); spin_unlock_bh(&session->lock); + mutex_unlock(&session->eh_mutex); } void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 5e573ef..0829b55 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -249,17 +249,17 @@ static void sas_ata_phy_reset(struct ata_port *ap) switch (dev->sata_dev.command_set) { case ATA_COMMAND_SET: SAS_DPRINTK("%s: Found ATA device.\n", __FUNCTION__); - ap->device[0].class = ATA_DEV_ATA; + ap->link.device[0].class = ATA_DEV_ATA; break; case ATAPI_COMMAND_SET: SAS_DPRINTK("%s: Found ATAPI device.\n", __FUNCTION__); - ap->device[0].class = ATA_DEV_ATAPI; + ap->link.device[0].class = ATA_DEV_ATAPI; break; default: SAS_DPRINTK("%s: Unknown SATA command set: %d.\n", __FUNCTION__, dev->sata_dev.command_set); - ap->device[0].class = ATA_DEV_UNKNOWN; + ap->link.device[0].class = ATA_DEV_UNKNOWN; break; } @@ -317,7 +317,7 @@ static int sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in, dev->sata_dev.serror = val; break; case SCR_ACTIVE: - dev->sata_dev.ap->sactive = val; + dev->sata_dev.ap->link.sactive = val; break; default: return -EINVAL; @@ -342,7 +342,7 @@ static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in, *val = dev->sata_dev.serror; return 0; case SCR_ACTIVE: - *val = dev->sata_dev.ap->sactive; + *val = dev->sata_dev.ap->link.sactive; return 0; default: return -EINVAL; @@ -350,7 +350,6 @@ static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in, } static struct ata_port_operations sas_sata_ops = { - .port_disable = ata_port_disable, .check_status = sas_ata_check_status, .check_altstatus = sas_ata_check_status, .dev_select = ata_noop_dev_select, diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 9023ec6..e7e11f2 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -1753,6 +1753,14 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len) *len = 0; + if (scsi_sg_count(cmd) == 1 && !adapter->has_64bit_addr) { + sg = scsi_sglist(cmd); + scb->dma_h_bulkdata = sg_dma_address(sg); + *buf = (u32)scb->dma_h_bulkdata; + *len = sg_dma_len(sg); + return 0; + } + scsi_for_each_sg(cmd, sg, sgcnt, idx) { if (adapter->has_64bit_addr) { scb->sgl64[idx].address = sg_dma_address(sg); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index fac3429..207f1aa 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -263,25 +263,12 @@ static int scsi_merge_bio(struct request *rq, struct bio *bio) bio->bi_rw |= (1 << BIO_RW); blk_queue_bounce(q, &bio); - if (!rq->bio) - blk_rq_bio_prep(q, rq, bio); - else if (!ll_back_merge_fn(q, rq, bio)) - return -EINVAL; - else { - rq->biotail->bi_next = bio; - rq->biotail = bio; - } - - return 0; + return blk_rq_append_bio(q, rq, bio); } -static int scsi_bi_endio(struct bio *bio, unsigned int bytes_done, int error) +static void scsi_bi_endio(struct bio *bio, int error) { - if (bio->bi_size) - return 1; - bio_put(bio); - return 0; } /** @@ -342,7 +329,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, if (bio->bi_vcnt >= nr_vecs) { err = scsi_merge_bio(rq, bio); if (err) { - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); goto free_bios; } bio = NULL; @@ -365,7 +352,7 @@ free_bios: /* * call endio instead of bio_put incase it was bounced */ - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); } return err; diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c index 4bf9aa5..40579ed 100644 --- a/drivers/scsi/scsi_netlink.c +++ b/drivers/scsi/scsi_netlink.c @@ -64,7 +64,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb) if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) { err = -EBADMSG; - goto next_msg; + return; } hdr = NLMSG_DATA(nlh); @@ -99,27 +99,6 @@ next_msg: /** - * scsi_nl_rcv_msg - - * Receive handler for a socket. Extracts a received message buffer from - * the socket, and starts message processing. - * - * @sk: socket - * @len: unused - * - **/ -static void -scsi_nl_rcv(struct sock *sk, int len) -{ - struct sk_buff *skb; - - while ((skb = skb_dequeue(&sk->sk_receive_queue))) { - scsi_nl_rcv_msg(skb); - kfree_skb(skb); - } -} - - -/** * scsi_nl_rcv_event - * Event handler for a netlink socket. * @@ -167,8 +146,8 @@ scsi_netlink_init(void) return; } - scsi_nl_sock = netlink_kernel_create(NETLINK_SCSITRANSPORT, - SCSI_NL_GRP_CNT, scsi_nl_rcv, NULL, + scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT, + SCSI_NL_GRP_CNT, scsi_nl_rcv_msg, NULL, THIS_MODULE); if (!scsi_nl_sock) { printk(KERN_ERR "%s: register of recieve handler failed\n", diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 8e880ef..daed37d 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -319,16 +319,11 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; } -static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct scsi_device *sdev = to_scsi_device(dev); - int i = 0; - int length = 0; - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); - envp[i] = NULL; + add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); return 0; } diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 34c1860..5428d15 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1097,61 +1097,49 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) } /* - * Get message from skb (based on rtnetlink_rcv_skb). Each message is - * processed by iscsi_if_recv_msg. Malformed skbs with wrong lengths or - * invalid creds are discarded silently. + * Get message from skb. Each message is processed by iscsi_if_recv_msg. + * Malformed skbs with wrong lengths or invalid creds are not processed. */ static void -iscsi_if_rx(struct sock *sk, int len) +iscsi_if_rx(struct sk_buff *skb) { - struct sk_buff *skb; - mutex_lock(&rx_queue_mutex); - while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { - if (NETLINK_CREDS(skb)->uid) { - skb_pull(skb, skb->len); - goto free_skb; + while (skb->len >= NLMSG_SPACE(0)) { + int err; + uint32_t rlen; + struct nlmsghdr *nlh; + struct iscsi_uevent *ev; + + nlh = nlmsg_hdr(skb); + if (nlh->nlmsg_len < sizeof(*nlh) || + skb->len < nlh->nlmsg_len) { + break; } - while (skb->len >= NLMSG_SPACE(0)) { - int err; - uint32_t rlen; - struct nlmsghdr *nlh; - struct iscsi_uevent *ev; + ev = NLMSG_DATA(nlh); + rlen = NLMSG_ALIGN(nlh->nlmsg_len); + if (rlen > skb->len) + rlen = skb->len; - nlh = nlmsg_hdr(skb); - if (nlh->nlmsg_len < sizeof(*nlh) || - skb->len < nlh->nlmsg_len) { - break; - } - - ev = NLMSG_DATA(nlh); - rlen = NLMSG_ALIGN(nlh->nlmsg_len); - if (rlen > skb->len) - rlen = skb->len; - - err = iscsi_if_recv_msg(skb, nlh); - if (err) { - ev->type = ISCSI_KEVENT_IF_ERROR; - ev->iferror = err; - } - do { - /* - * special case for GET_STATS: - * on success - sending reply and stats from - * inside of if_recv_msg(), - * on error - fall through. - */ - if (ev->type == ISCSI_UEVENT_GET_STATS && !err) - break; - err = iscsi_if_send_reply( - NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq, - nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); - } while (err < 0 && err != -ECONNREFUSED); - skb_pull(skb, rlen); + err = iscsi_if_recv_msg(skb, nlh); + if (err) { + ev->type = ISCSI_KEVENT_IF_ERROR; + ev->iferror = err; } -free_skb: - kfree_skb(skb); + do { + /* + * special case for GET_STATS: + * on success - sending reply and stats from + * inside of if_recv_msg(), + * on error - fall through. + */ + if (ev->type == ISCSI_UEVENT_GET_STATS && !err) + break; + err = iscsi_if_send_reply( + NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq, + nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); + } while (err < 0 && err != -ECONNREFUSED); + skb_pull(skb, rlen); } mutex_unlock(&rx_queue_mutex); } @@ -1523,7 +1511,7 @@ static __init int iscsi_transport_init(void) if (err) goto unregister_conn_class; - nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, NULL, + nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx, NULL, THIS_MODULE); if (!nls) { err = -ENOBUFS; diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 6f56f87..4df21c9 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -787,10 +787,12 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) struct scsi_target *starget = sdev->sdev_target; struct Scsi_Host *shost = sdev->host; int len = sdev->inquiry_len; + int min_period = spi_min_period(starget); + int max_width = spi_max_width(starget); /* first set us up for narrow async */ DV_SET(offset, 0); DV_SET(width, 0); - + if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS) != SPI_COMPARE_SUCCESS) { starget_printk(KERN_ERR, starget, "Domain Validation Initial Inquiry Failed\n"); @@ -798,9 +800,13 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) return; } + if (!scsi_device_wide(sdev)) { + spi_max_width(starget) = 0; + max_width = 0; + } + /* test width */ - if (i->f->set_width && spi_max_width(starget) && - scsi_device_wide(sdev)) { + if (i->f->set_width && max_width) { i->f->set_width(starget, 1); if (spi_dv_device_compare_inquiry(sdev, buffer, @@ -809,6 +815,11 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) != SPI_COMPARE_SUCCESS) { starget_printk(KERN_ERR, starget, "Wide Transfers Fail\n"); i->f->set_width(starget, 0); + /* Make sure we don't force wide back on by asking + * for a transfer period that requires it */ + max_width = 0; + if (min_period < 10) + min_period = 10; } } @@ -828,7 +839,8 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) /* now set up to the maximum */ DV_SET(offset, spi_max_offset(starget)); - DV_SET(period, spi_min_period(starget)); + DV_SET(period, min_period); + /* try QAS requests; this should be harmless to set if the * target supports it */ if (scsi_device_qas(sdev)) { @@ -837,14 +849,14 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) DV_SET(qas, 0); } - if (scsi_device_ius(sdev) && spi_min_period(starget) < 9) { + if (scsi_device_ius(sdev) && min_period < 9) { /* This u320 (or u640). Set IU transfers */ DV_SET(iu, 1); /* Then set the optional parameters */ DV_SET(rd_strm, 1); DV_SET(wr_flow, 1); DV_SET(rti, 1); - if (spi_min_period(starget) == 8) + if (min_period == 8) DV_SET(pcomp_en, 1); } else { DV_SET(iu, 0); @@ -862,6 +874,10 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) } else { DV_SET(dt, 1); } + /* set width last because it will pull all the other + * parameters down to required values */ + DV_SET(width, max_width); + /* Do the read only INQUIRY tests */ spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len, spi_dv_device_compare_inquiry); |