diff --git a/[refs] b/[refs] index 5cc29e03e86c..e8cfc43b684e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 53abbf7eeab22620586cbba272e569fd3e729b0b +refs/heads/master: 7fb6ec287a05d7a71ec086d8bc9a452d5e16ff1a diff --git a/trunk/drivers/net/8139cp.c b/trunk/drivers/net/8139cp.c index bc537440ca02..34b80de34fae 100644 --- a/trunk/drivers/net/8139cp.c +++ b/trunk/drivers/net/8139cp.c @@ -353,6 +353,8 @@ struct cp_private { struct net_device_stats net_stats; struct cp_extra_stats cp_stats; + struct cp_dma_stats *nic_stats; + dma_addr_t nic_stats_dma; unsigned rx_tail ____cacheline_aligned; struct cp_desc *rx_ring; @@ -1141,6 +1143,10 @@ static int cp_alloc_rings (struct cp_private *cp) cp->rx_ring = mem; cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE]; + mem += (CP_RING_BYTES - CP_STATS_SIZE); + cp->nic_stats = mem; + cp->nic_stats_dma = cp->ring_dma + (CP_RING_BYTES - CP_STATS_SIZE); + return cp_init_rings(cp); } @@ -1181,6 +1187,7 @@ static void cp_free_rings (struct cp_private *cp) pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma); cp->rx_ring = NULL; cp->tx_ring = NULL; + cp->nic_stats = NULL; } static int cp_open (struct net_device *dev) @@ -1509,17 +1516,13 @@ static void cp_get_ethtool_stats (struct net_device *dev, struct ethtool_stats *estats, u64 *tmp_stats) { struct cp_private *cp = netdev_priv(dev); - struct cp_dma_stats *nic_stats; - dma_addr_t dma; int i; - nic_stats = pci_alloc_consistent(cp->pdev, sizeof(*nic_stats), &dma); - if (!nic_stats) - return; + memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats)); /* begin NIC statistics dump */ - cpw32(StatsAddr + 4, (u64)dma >> 32); - cpw32(StatsAddr, ((u64)dma & DMA_32BIT_MASK) | DumpStats); + cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16); + cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats); cpr32(StatsAddr); for (i = 0; i < 1000; i++) { @@ -1529,27 +1532,24 @@ static void cp_get_ethtool_stats (struct net_device *dev, } cpw32(StatsAddr, 0); cpw32(StatsAddr + 4, 0); - cpr32(StatsAddr); i = 0; - tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok); - tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok); - tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err); - tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err); - tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo); - tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align); - tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col); - tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol); - tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys); - tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast); - tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast); - tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort); - tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun); + tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok); + tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok); + tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_err); + tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_err); + tmp_stats[i++] = le16_to_cpu(cp->nic_stats->rx_fifo); + tmp_stats[i++] = le16_to_cpu(cp->nic_stats->frame_align); + tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_1col); + tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_mcol); + tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_phys); + tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_bcast); + tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_ok_mcast); + tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_abort); + tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_underrun); tmp_stats[i++] = cp->cp_stats.rx_frags; if (i != CP_NUM_STATS) BUG(); - - pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma); } static struct ethtool_ops cp_ethtool_ops = { diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index f8dedb623dc0..94c9f68dd16b 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -2879,7 +2879,6 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) * This target is not on a VLAN */ if (rt->u.dst.dev == bond->dev) { - ip_rt_put(rt); dprintk("basa: rtdev == bond->dev: arp_send\n"); bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], bond->master_ip, 0); @@ -2899,7 +2898,6 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) } if (vlan_id) { - ip_rt_put(rt); bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], vlan->vlan_ip, vlan_id); continue; @@ -2911,7 +2909,6 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) bond->dev->name, NIPQUAD(fl.fl4_dst), rt->u.dst.dev ? rt->u.dst.dev->name : "NULL"); } - ip_rt_put(rt); } } diff --git a/trunk/drivers/net/spider_net.c b/trunk/drivers/net/spider_net.c index c796f41b4a52..4e19220473d0 100644 --- a/trunk/drivers/net/spider_net.c +++ b/trunk/drivers/net/spider_net.c @@ -1817,10 +1817,6 @@ spider_net_setup_phy(struct spider_net_card *card) /* LEDs active in both modes, autosense prio = fiber */ spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f); - /* switch off fibre autoneg */ - spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01); - spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004); - phy->def->ops->read_link(phy); pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name, phy->speed, phy->duplex==1 ? "Full" : "Half"); diff --git a/trunk/drivers/s390/net/qeth.h b/trunk/drivers/s390/net/qeth.h index 2ad4797ce024..3a0285669adf 100644 --- a/trunk/drivers/s390/net/qeth.h +++ b/trunk/drivers/s390/net/qeth.h @@ -24,7 +24,7 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.142 $" +#define VERSION_QETH_H "$Revision: 1.139 $" #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" @@ -1172,7 +1172,7 @@ extern int qeth_realloc_buffer_pool(struct qeth_card *, int); extern int -qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types); +qeth_set_large_send(struct qeth_card *); extern void qeth_fill_header(struct qeth_card *, struct qeth_hdr *, diff --git a/trunk/drivers/s390/net/qeth_main.c b/trunk/drivers/s390/net/qeth_main.c index 86582cf1e19e..79c74f3a11f5 100644 --- a/trunk/drivers/s390/net/qeth_main.c +++ b/trunk/drivers/s390/net/qeth_main.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $) + * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,7 +12,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Thomas Spatzier * - * $Revision: 1.224 $ $Date: 2005/05/04 20:19:18 $ + * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +29,14 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/*** + * eye catcher; just for debugging purposes + */ +void volatile +qeth_eyecatcher(void) +{ + return; +} #include #include @@ -72,7 +80,7 @@ #include "qeth_eddp.h" #include "qeth_tso.h" -#define VERSION_QETH_C "$Revision: 1.224 $" +#define VERSION_QETH_C "$Revision: 1.214 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -2751,9 +2759,11 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, queue->card->perf_stats.outbound_do_qdio_start_time; #endif if (rc){ + QETH_DBF_SPRINTF(trace, 0, "qeth_flush_buffers: do_QDIO " + "returned error (%i) on device %s.", + rc, CARD_DDEV_ID(queue->card)); QETH_DBF_TEXT(trace, 2, "flushbuf"); QETH_DBF_TEXT_(trace, 2, " err%d", rc); - QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card)); queue->card->stats.tx_errors += count; /* this must not happen under normal circumstances. if it * happens something is really wrong -> recover */ @@ -2899,8 +2909,11 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, QETH_DBF_TEXT(trace, 6, "qdouhdl"); if (status & QDIO_STATUS_LOOK_FOR_ERROR) { if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ - QETH_DBF_TEXT(trace, 2, "achkcond"); - QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card)); + QETH_DBF_SPRINTF(trace, 2, "On device %s: " + "received active check " + "condition (0x%08x).", + CARD_BUS_ID(card), status); + QETH_DBF_TEXT(trace, 2, "chkcond"); QETH_DBF_TEXT_(trace, 2, "%08x", status); netif_stop_queue(card->dev); qeth_schedule_recovery(card); @@ -3343,32 +3356,26 @@ qeth_halt_channel(struct qeth_channel *channel) static int qeth_halt_channels(struct qeth_card *card) { - int rc1 = 0, rc2=0, rc3 = 0; + int rc = 0; QETH_DBF_TEXT(trace,3,"haltchs"); - rc1 = qeth_halt_channel(&card->read); - rc2 = qeth_halt_channel(&card->write); - rc3 = qeth_halt_channel(&card->data); - if (rc1) - return rc1; - if (rc2) - return rc2; - return rc3; + if ((rc = qeth_halt_channel(&card->read))) + return rc; + if ((rc = qeth_halt_channel(&card->write))) + return rc; + return qeth_halt_channel(&card->data); } static int qeth_clear_channels(struct qeth_card *card) { - int rc1 = 0, rc2=0, rc3 = 0; + int rc = 0; QETH_DBF_TEXT(trace,3,"clearchs"); - rc1 = qeth_clear_channel(&card->read); - rc2 = qeth_clear_channel(&card->write); - rc3 = qeth_clear_channel(&card->data); - if (rc1) - return rc1; - if (rc2) - return rc2; - return rc3; + if ((rc = qeth_clear_channel(&card->read))) + return rc; + if ((rc = qeth_clear_channel(&card->write))) + return rc; + return qeth_clear_channel(&card->data); } static int @@ -3438,23 +3445,23 @@ qeth_mpc_initialize(struct qeth_card *card) } if ((rc = qeth_cm_enable(card))){ QETH_DBF_TEXT_(setup, 2, "2err%d", rc); - goto out_qdio; + return rc; } if ((rc = qeth_cm_setup(card))){ QETH_DBF_TEXT_(setup, 2, "3err%d", rc); - goto out_qdio; + return rc; } if ((rc = qeth_ulp_enable(card))){ QETH_DBF_TEXT_(setup, 2, "4err%d", rc); - goto out_qdio; + return rc; } if ((rc = qeth_ulp_setup(card))){ QETH_DBF_TEXT_(setup, 2, "5err%d", rc); - goto out_qdio; + return rc; } if ((rc = qeth_alloc_qdio_buffers(card))){ QETH_DBF_TEXT_(setup, 2, "5err%d", rc); - goto out_qdio; + return rc; } if ((rc = qeth_qdio_establish(card))){ QETH_DBF_TEXT_(setup, 2, "6err%d", rc); @@ -3788,16 +3795,12 @@ static inline int qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, struct qeth_hdr **hdr, int ipv) { - int rc; #ifdef CONFIG_QETH_VLAN u16 *tag; #endif QETH_DBF_TEXT(trace, 6, "prepskb"); - rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); - if (rc) - return rc; #ifdef CONFIG_QETH_VLAN if (card->vlangrp && vlan_tx_tag_present(*skb) && ((ipv == 6) || card->options.layer2) ) { @@ -4248,8 +4251,7 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, } static inline int -qeth_get_elements_no(struct qeth_card *card, void *hdr, - struct sk_buff *skb, int elems) +qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) { int elements_needed = 0; @@ -4259,10 +4261,9 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, if (elements_needed == 0 ) elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) + skb->len) >> PAGE_SHIFT); - if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){ + if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ PRINT_ERR("qeth_do_send_packet: invalid size of " - "IP packet (Number=%d / Length=%d). Discarded.\n", - (elements_needed+elems), skb->len); + "IP packet. Discarded."); return 0; } return elements_needed; @@ -4274,7 +4275,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) int ipv = 0; int cast_type; struct qeth_qdio_out_q *queue; - struct qeth_hdr *hdr = NULL; + struct qeth_hdr *hdr; int elements_needed = 0; enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; struct qeth_eddp_context *ctx = NULL; @@ -4336,11 +4337,9 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) return -EINVAL; } } else { - int elems = qeth_get_elements_no(card,(void*) hdr, skb, - elements_needed); - if (!elems) + elements_needed += qeth_get_elements_no(card,(void*) hdr, skb); + if (!elements_needed) return -EINVAL; - elements_needed += elems; } if (card->info.type != QETH_CARD_TYPE_IQD) @@ -4505,11 +4504,7 @@ qeth_arp_set_no_entries(struct qeth_card *card, int no_entries) QETH_DBF_TEXT(trace,3,"arpstnoe"); - /* - * currently GuestLAN only supports the ARP assist function - * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES; - * thus we say EOPNOTSUPP for this ARP function - */ + /* TODO: really not supported by GuestLAN? */ if (card->info.guestlan) return -EOPNOTSUPP; if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { @@ -4686,6 +4681,14 @@ qeth_arp_query(struct qeth_card *card, char *udata) QETH_DBF_TEXT(trace,3,"arpquery"); + /* + * currently GuestLAN does only deliver all zeros on query arp, + * even though arp processing is supported (according to IPA supp. + * funcs flags); since all zeros is no valueable information, + * we say EOPNOTSUPP for all ARP functions + */ + /*if (card->info.guestlan) + return -EOPNOTSUPP; */ if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ IPA_ARP_PROCESSING)) { PRINT_WARN("ARP processing not supported " @@ -4891,9 +4894,10 @@ qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry) QETH_DBF_TEXT(trace,3,"arpadent"); /* - * currently GuestLAN only supports the ARP assist function - * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY; - * thus we say EOPNOTSUPP for this ARP function + * currently GuestLAN does only deliver all zeros on query arp, + * even though arp processing is supported (according to IPA supp. + * funcs flags); since all zeros is no valueable information, + * we say EOPNOTSUPP for all ARP functions */ if (card->info.guestlan) return -EOPNOTSUPP; @@ -4933,9 +4937,10 @@ qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry QETH_DBF_TEXT(trace,3,"arprment"); /* - * currently GuestLAN only supports the ARP assist function - * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY; - * thus we say EOPNOTSUPP for this ARP function + * currently GuestLAN does only deliver all zeros on query arp, + * even though arp processing is supported (according to IPA supp. + * funcs flags); since all zeros is no valueable information, + * we say EOPNOTSUPP for all ARP functions */ if (card->info.guestlan) return -EOPNOTSUPP; @@ -4973,10 +4978,11 @@ qeth_arp_flush_cache(struct qeth_card *card) QETH_DBF_TEXT(trace,3,"arpflush"); /* - * currently GuestLAN only supports the ARP assist function - * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE; - * thus we say EOPNOTSUPP for this ARP function - */ + * currently GuestLAN does only deliver all zeros on query arp, + * even though arp processing is supported (according to IPA supp. + * funcs flags); since all zeros is no valueable information, + * we say EOPNOTSUPP for all ARP functions + */ if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD)) return -EOPNOTSUPP; if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { @@ -7032,16 +7038,14 @@ qeth_setrouting_v6(struct qeth_card *card) } int -qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type) +qeth_set_large_send(struct qeth_card *card) { int rc = 0; - if (card->dev == NULL) { - card->options.large_send = type; + if (card->dev == NULL) return 0; - } + netif_stop_queue(card->dev); - card->options.large_send = type; switch (card->options.large_send) { case QETH_LARGE_SEND_EDDP: card->dev->features |= NETIF_F_TSO | NETIF_F_SG; @@ -7062,6 +7066,7 @@ qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type) card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); break; } + netif_wake_queue(card->dev); return rc; } @@ -8252,6 +8257,7 @@ qeth_init(void) { int rc=0; + qeth_eyecatcher(); PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n", version, VERSION_QETH_C, VERSION_QETH_H, VERSION_QETH_MPC_H, VERSION_QETH_MPC_C, @@ -8332,6 +8338,7 @@ __exit qeth_exit(void) printk("qeth: removed\n"); } +EXPORT_SYMBOL(qeth_eyecatcher); module_init(qeth_init); module_exit(qeth_exit); MODULE_AUTHOR("Frank Pavlic "); diff --git a/trunk/drivers/s390/net/qeth_sys.c b/trunk/drivers/s390/net/qeth_sys.c index dda105b73063..98bedb0cb387 100644 --- a/trunk/drivers/s390/net/qeth_sys.c +++ b/trunk/drivers/s390/net/qeth_sys.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.54 $) + * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.51 $) * * Linux on zSeries OSA Express and HiperSockets support * This file contains code related to sysfs. @@ -20,7 +20,7 @@ #include "qeth_mpc.h" #include "qeth_fs.h" -const char *VERSION_QETH_SYS_C = "$Revision: 1.54 $"; +const char *VERSION_QETH_SYS_C = "$Revision: 1.51 $"; /*****************************************************************************/ /* */ @@ -722,13 +722,10 @@ qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const c if (!card) return -EINVAL; - if (card->info.type == QETH_CARD_TYPE_IQD) { - PRINT_WARN("Layer2 on Hipersockets is not supported! \n"); - return -EPERM; - } if (((card->state != CARD_STATE_DOWN) && - (card->state != CARD_STATE_RECOVER))) + (card->state != CARD_STATE_RECOVER)) || + (card->info.type != QETH_CARD_TYPE_OSAE)) return -EPERM; i = simple_strtoul(buf, &tmp, 16); @@ -774,7 +771,9 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con if (!card) return -EINVAL; + tmp = strsep((char **) &buf, "\n"); + if (!strcmp(tmp, "no")){ type = QETH_LARGE_SEND_NO; } else if (!strcmp(tmp, "EDDP")) { @@ -787,8 +786,10 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con } if (card->options.large_send == type) return count; - if ((rc = qeth_set_large_send(card, type))) + card->options.large_send = type; + if ((rc = qeth_set_large_send(card))) return rc; + return count; } diff --git a/trunk/drivers/scsi/libata-core.c b/trunk/drivers/scsi/libata-core.c index 5cc53cd9323e..d92273cbe0de 100644 --- a/trunk/drivers/scsi/libata-core.c +++ b/trunk/drivers/scsi/libata-core.c @@ -2465,9 +2465,12 @@ static unsigned long ata_pio_poll(struct ata_port *ap) * * LOCKING: * None. (executing in kernel thread context) + * + * RETURNS: + * Non-zero if qc completed, zero otherwise. */ -static void ata_pio_complete (struct ata_port *ap) +static int ata_pio_complete (struct ata_port *ap) { struct ata_queued_cmd *qc; u8 drv_stat; @@ -2486,14 +2489,14 @@ static void ata_pio_complete (struct ata_port *ap) if (drv_stat & (ATA_BUSY | ATA_DRQ)) { ap->pio_task_state = PIO_ST_LAST_POLL; ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; - return; + return 0; } } drv_stat = ata_wait_idle(ap); if (!ata_ok(drv_stat)) { ap->pio_task_state = PIO_ST_ERR; - return; + return 0; } qc = ata_qc_from_tag(ap, ap->active_tag); @@ -2502,6 +2505,10 @@ static void ata_pio_complete (struct ata_port *ap) ap->pio_task_state = PIO_ST_IDLE; ata_poll_qc_complete(qc, drv_stat); + + /* another command may start at this point */ + + return 1; } @@ -2709,7 +2716,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) next_sg: if (unlikely(qc->cursg >= qc->n_elem)) { - /* + /* * The end of qc->sg is reached and the device expects * more data to transfer. In order not to overrun qc->sg * and fulfill length specified in the byte count register, @@ -2721,7 +2728,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) unsigned int i; if (words) /* warning if bytes > 1 */ - printk(KERN_WARNING "ata%u: %u bytes trailing data\n", + printk(KERN_WARNING "ata%u: %u bytes trailing data\n", ap->id, bytes); for (i = 0; i < words; i++) @@ -2849,9 +2856,7 @@ static void ata_pio_block(struct ata_port *ap) if (is_atapi_taskfile(&qc->tf)) { /* no more data to transfer or unsupported ATAPI command */ if ((status & ATA_DRQ) == 0) { - ap->pio_task_state = PIO_ST_IDLE; - - ata_poll_qc_complete(qc, status); + ap->pio_task_state = PIO_ST_LAST; return; } @@ -2887,7 +2892,12 @@ static void ata_pio_error(struct ata_port *ap) static void ata_pio_task(void *_data) { struct ata_port *ap = _data; - unsigned long timeout = 0; + unsigned long timeout; + int qc_completed; + +fsm_start: + timeout = 0; + qc_completed = 0; switch (ap->pio_task_state) { case PIO_ST_IDLE: @@ -2898,7 +2908,7 @@ static void ata_pio_task(void *_data) break; case PIO_ST_LAST: - ata_pio_complete(ap); + qc_completed = ata_pio_complete(ap); break; case PIO_ST_POLL: @@ -2913,10 +2923,9 @@ static void ata_pio_task(void *_data) } if (timeout) - queue_delayed_work(ata_wq, &ap->pio_task, - timeout); - else - queue_work(ata_wq, &ap->pio_task); + queue_delayed_work(ata_wq, &ap->pio_task, timeout); + else if (!qc_completed) + goto fsm_start; } static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,