Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6: firewire: use split transaction timeout only for split transactions firewire: ohci: consolidate context status flags firewire: ohci: cache the context run bit firewire: ohci: flush AT contexts after bus reset - addendum firewire: ohci: flush AT contexts after bus reset for OHCI 1.2 firewire: net: set carrier state at ifup firewire: net: add carrier detection firewire: net: ratelimit error messages firewire: ohci: restart iso DMA contexts on resume from low power mode firewire: ohci: restore GUID on resume. firewire: ohci: use common buffer for self IDs and AR descriptors firewire: ohci: optimize iso context checks in the interrupt handler firewire: make PHY packet header format consistent firewire: ohci: properly clear posted write errors firewire: ohci: flush MMIO writes in the interrupt handler firewire: ohci: fix AT context initialization error handling firewire: ohci: Asynchronous Reception rewrite firewire: core: Update WARN uses firewire: nosy: char device is not seekable
This commit is contained in:
@@ -19,7 +19,7 @@ config FIREWIRE
|
|||||||
|
|
||||||
config FIREWIRE_OHCI
|
config FIREWIRE_OHCI
|
||||||
tristate "OHCI-1394 controllers"
|
tristate "OHCI-1394 controllers"
|
||||||
depends on PCI && FIREWIRE
|
depends on PCI && FIREWIRE && MMU
|
||||||
help
|
help
|
||||||
Enable this driver if you have a FireWire controller based
|
Enable this driver if you have a FireWire controller based
|
||||||
on the OHCI specification. For all practical purposes, this
|
on the OHCI specification. For all practical purposes, this
|
||||||
|
@@ -1501,9 +1501,10 @@ static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)
|
|||||||
e->client = client;
|
e->client = client;
|
||||||
e->p.speed = SCODE_100;
|
e->p.speed = SCODE_100;
|
||||||
e->p.generation = a->generation;
|
e->p.generation = a->generation;
|
||||||
e->p.header[0] = a->data[0];
|
e->p.header[0] = TCODE_LINK_INTERNAL << 4;
|
||||||
e->p.header[1] = a->data[1];
|
e->p.header[1] = a->data[0];
|
||||||
e->p.header_length = 8;
|
e->p.header[2] = a->data[1];
|
||||||
|
e->p.header_length = 12;
|
||||||
e->p.callback = outbound_phy_packet_callback;
|
e->p.callback = outbound_phy_packet_callback;
|
||||||
e->phy_packet.closure = a->closure;
|
e->phy_packet.closure = a->closure;
|
||||||
e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_SENT;
|
e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_SENT;
|
||||||
|
@@ -72,6 +72,15 @@
|
|||||||
#define PHY_CONFIG_ROOT_ID(node_id) ((((node_id) & 0x3f) << 24) | (1 << 23))
|
#define PHY_CONFIG_ROOT_ID(node_id) ((((node_id) & 0x3f) << 24) | (1 << 23))
|
||||||
#define PHY_IDENTIFIER(id) ((id) << 30)
|
#define PHY_IDENTIFIER(id) ((id) << 30)
|
||||||
|
|
||||||
|
/* returns 0 if the split timeout handler is already running */
|
||||||
|
static int try_cancel_split_timeout(struct fw_transaction *t)
|
||||||
|
{
|
||||||
|
if (t->is_split_transaction)
|
||||||
|
return del_timer(&t->split_timeout_timer);
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int close_transaction(struct fw_transaction *transaction,
|
static int close_transaction(struct fw_transaction *transaction,
|
||||||
struct fw_card *card, int rcode)
|
struct fw_card *card, int rcode)
|
||||||
{
|
{
|
||||||
@@ -81,7 +90,7 @@ static int close_transaction(struct fw_transaction *transaction,
|
|||||||
spin_lock_irqsave(&card->lock, flags);
|
spin_lock_irqsave(&card->lock, flags);
|
||||||
list_for_each_entry(t, &card->transaction_list, link) {
|
list_for_each_entry(t, &card->transaction_list, link) {
|
||||||
if (t == transaction) {
|
if (t == transaction) {
|
||||||
if (!del_timer(&t->split_timeout_timer)) {
|
if (!try_cancel_split_timeout(t)) {
|
||||||
spin_unlock_irqrestore(&card->lock, flags);
|
spin_unlock_irqrestore(&card->lock, flags);
|
||||||
goto timed_out;
|
goto timed_out;
|
||||||
}
|
}
|
||||||
@@ -141,16 +150,28 @@ static void split_transaction_timeout_callback(unsigned long data)
|
|||||||
card->tlabel_mask &= ~(1ULL << t->tlabel);
|
card->tlabel_mask &= ~(1ULL << t->tlabel);
|
||||||
spin_unlock_irqrestore(&card->lock, flags);
|
spin_unlock_irqrestore(&card->lock, flags);
|
||||||
|
|
||||||
card->driver->cancel_packet(card, &t->packet);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* At this point cancel_packet will never call the transaction
|
|
||||||
* callback, since we just took the transaction out of the list.
|
|
||||||
* So do it here.
|
|
||||||
*/
|
|
||||||
t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
|
t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void start_split_transaction_timeout(struct fw_transaction *t,
|
||||||
|
struct fw_card *card)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&card->lock, flags);
|
||||||
|
|
||||||
|
if (list_empty(&t->link) || WARN_ON(t->is_split_transaction)) {
|
||||||
|
spin_unlock_irqrestore(&card->lock, flags);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->is_split_transaction = true;
|
||||||
|
mod_timer(&t->split_timeout_timer,
|
||||||
|
jiffies + card->split_timeout_jiffies);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&card->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
static void transmit_complete_callback(struct fw_packet *packet,
|
static void transmit_complete_callback(struct fw_packet *packet,
|
||||||
struct fw_card *card, int status)
|
struct fw_card *card, int status)
|
||||||
{
|
{
|
||||||
@@ -162,7 +183,7 @@ static void transmit_complete_callback(struct fw_packet *packet,
|
|||||||
close_transaction(t, card, RCODE_COMPLETE);
|
close_transaction(t, card, RCODE_COMPLETE);
|
||||||
break;
|
break;
|
||||||
case ACK_PENDING:
|
case ACK_PENDING:
|
||||||
t->timestamp = packet->timestamp;
|
start_split_transaction_timeout(t, card);
|
||||||
break;
|
break;
|
||||||
case ACK_BUSY_X:
|
case ACK_BUSY_X:
|
||||||
case ACK_BUSY_A:
|
case ACK_BUSY_A:
|
||||||
@@ -250,7 +271,7 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WARN(1, "wrong tcode %d", tcode);
|
WARN(1, "wrong tcode %d\n", tcode);
|
||||||
}
|
}
|
||||||
common:
|
common:
|
||||||
packet->speed = speed;
|
packet->speed = speed;
|
||||||
@@ -349,11 +370,9 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
|
|||||||
t->node_id = destination_id;
|
t->node_id = destination_id;
|
||||||
t->tlabel = tlabel;
|
t->tlabel = tlabel;
|
||||||
t->card = card;
|
t->card = card;
|
||||||
|
t->is_split_transaction = false;
|
||||||
setup_timer(&t->split_timeout_timer,
|
setup_timer(&t->split_timeout_timer,
|
||||||
split_transaction_timeout_callback, (unsigned long)t);
|
split_transaction_timeout_callback, (unsigned long)t);
|
||||||
/* FIXME: start this timer later, relative to t->timestamp */
|
|
||||||
mod_timer(&t->split_timeout_timer,
|
|
||||||
jiffies + card->split_timeout_jiffies);
|
|
||||||
t->callback = callback;
|
t->callback = callback;
|
||||||
t->callback_data = callback_data;
|
t->callback_data = callback_data;
|
||||||
|
|
||||||
@@ -423,7 +442,8 @@ static void transmit_phy_packet_callback(struct fw_packet *packet,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct fw_packet phy_config_packet = {
|
static struct fw_packet phy_config_packet = {
|
||||||
.header_length = 8,
|
.header_length = 12,
|
||||||
|
.header[0] = TCODE_LINK_INTERNAL << 4,
|
||||||
.payload_length = 0,
|
.payload_length = 0,
|
||||||
.speed = SCODE_100,
|
.speed = SCODE_100,
|
||||||
.callback = transmit_phy_packet_callback,
|
.callback = transmit_phy_packet_callback,
|
||||||
@@ -451,8 +471,8 @@ void fw_send_phy_config(struct fw_card *card,
|
|||||||
|
|
||||||
mutex_lock(&phy_config_mutex);
|
mutex_lock(&phy_config_mutex);
|
||||||
|
|
||||||
phy_config_packet.header[0] = data;
|
phy_config_packet.header[1] = data;
|
||||||
phy_config_packet.header[1] = ~data;
|
phy_config_packet.header[2] = ~data;
|
||||||
phy_config_packet.generation = generation;
|
phy_config_packet.generation = generation;
|
||||||
INIT_COMPLETION(phy_config_done);
|
INIT_COMPLETION(phy_config_done);
|
||||||
|
|
||||||
@@ -638,7 +658,7 @@ int fw_get_response_length(struct fw_request *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WARN(1, "wrong tcode %d", tcode);
|
WARN(1, "wrong tcode %d\n", tcode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -694,7 +714,7 @@ void fw_fill_response(struct fw_packet *response, u32 *request_header,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WARN(1, "wrong tcode %d", tcode);
|
WARN(1, "wrong tcode %d\n", tcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
response->payload_mapped = false;
|
response->payload_mapped = false;
|
||||||
@@ -925,7 +945,7 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
|
|||||||
spin_lock_irqsave(&card->lock, flags);
|
spin_lock_irqsave(&card->lock, flags);
|
||||||
list_for_each_entry(t, &card->transaction_list, link) {
|
list_for_each_entry(t, &card->transaction_list, link) {
|
||||||
if (t->node_id == source && t->tlabel == tlabel) {
|
if (t->node_id == source && t->tlabel == tlabel) {
|
||||||
if (!del_timer(&t->split_timeout_timer)) {
|
if (!try_cancel_split_timeout(t)) {
|
||||||
spin_unlock_irqrestore(&card->lock, flags);
|
spin_unlock_irqrestore(&card->lock, flags);
|
||||||
goto timed_out;
|
goto timed_out;
|
||||||
}
|
}
|
||||||
|
@@ -215,9 +215,11 @@ static inline bool is_next_generation(int new_generation, int old_generation)
|
|||||||
|
|
||||||
/* -transaction */
|
/* -transaction */
|
||||||
|
|
||||||
|
#define TCODE_LINK_INTERNAL 0xe
|
||||||
|
|
||||||
#define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4)
|
#define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4)
|
||||||
#define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0)
|
#define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0)
|
||||||
#define TCODE_IS_LINK_INTERNAL(tcode) ((tcode) == 0xe)
|
#define TCODE_IS_LINK_INTERNAL(tcode) ((tcode) == TCODE_LINK_INTERNAL)
|
||||||
#define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0)
|
#define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0)
|
||||||
#define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0)
|
#define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0)
|
||||||
#define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4)
|
#define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4)
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
#include <linux/bug.h>
|
#include <linux/bug.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
#include <linux/firewire.h>
|
#include <linux/firewire.h>
|
||||||
#include <linux/firewire-constants.h>
|
#include <linux/firewire-constants.h>
|
||||||
#include <linux/highmem.h>
|
#include <linux/highmem.h>
|
||||||
@@ -179,6 +180,7 @@ struct fwnet_device {
|
|||||||
/* Number of tx datagrams that have been queued but not yet acked */
|
/* Number of tx datagrams that have been queued but not yet acked */
|
||||||
int queued_datagrams;
|
int queued_datagrams;
|
||||||
|
|
||||||
|
int peer_count;
|
||||||
struct list_head peer_list;
|
struct list_head peer_list;
|
||||||
struct fw_card *card;
|
struct fw_card *card;
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
@@ -996,15 +998,23 @@ static void fwnet_transmit_packet_failed(struct fwnet_packet_task *ptask)
|
|||||||
static void fwnet_write_complete(struct fw_card *card, int rcode,
|
static void fwnet_write_complete(struct fw_card *card, int rcode,
|
||||||
void *payload, size_t length, void *data)
|
void *payload, size_t length, void *data)
|
||||||
{
|
{
|
||||||
struct fwnet_packet_task *ptask;
|
struct fwnet_packet_task *ptask = data;
|
||||||
|
static unsigned long j;
|
||||||
ptask = data;
|
static int last_rcode, errors_skipped;
|
||||||
|
|
||||||
if (rcode == RCODE_COMPLETE) {
|
if (rcode == RCODE_COMPLETE) {
|
||||||
fwnet_transmit_packet_done(ptask);
|
fwnet_transmit_packet_done(ptask);
|
||||||
} else {
|
} else {
|
||||||
fw_error("fwnet_write_complete: failed: %x\n", rcode);
|
|
||||||
fwnet_transmit_packet_failed(ptask);
|
fwnet_transmit_packet_failed(ptask);
|
||||||
|
|
||||||
|
if (printk_timed_ratelimit(&j, 1000) || rcode != last_rcode) {
|
||||||
|
fw_error("fwnet_write_complete: "
|
||||||
|
"failed: %x (skipped %d)\n", rcode, errors_skipped);
|
||||||
|
|
||||||
|
errors_skipped = 0;
|
||||||
|
last_rcode = rcode;
|
||||||
|
} else
|
||||||
|
errors_skipped++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1213,6 +1223,14 @@ static int fwnet_broadcast_start(struct fwnet_device *dev)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_carrier_state(struct fwnet_device *dev)
|
||||||
|
{
|
||||||
|
if (dev->peer_count > 1)
|
||||||
|
netif_carrier_on(dev->netdev);
|
||||||
|
else
|
||||||
|
netif_carrier_off(dev->netdev);
|
||||||
|
}
|
||||||
|
|
||||||
/* ifup */
|
/* ifup */
|
||||||
static int fwnet_open(struct net_device *net)
|
static int fwnet_open(struct net_device *net)
|
||||||
{
|
{
|
||||||
@@ -1226,6 +1244,10 @@ static int fwnet_open(struct net_device *net)
|
|||||||
}
|
}
|
||||||
netif_start_queue(net);
|
netif_start_queue(net);
|
||||||
|
|
||||||
|
spin_lock_irq(&dev->lock);
|
||||||
|
set_carrier_state(dev);
|
||||||
|
spin_unlock_irq(&dev->lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1397,6 +1419,10 @@ static int fwnet_change_mtu(struct net_device *net, int new_mtu)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct ethtool_ops fwnet_ethtool_ops = {
|
||||||
|
.get_link = ethtool_op_get_link,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct net_device_ops fwnet_netdev_ops = {
|
static const struct net_device_ops fwnet_netdev_ops = {
|
||||||
.ndo_open = fwnet_open,
|
.ndo_open = fwnet_open,
|
||||||
.ndo_stop = fwnet_stop,
|
.ndo_stop = fwnet_stop,
|
||||||
@@ -1415,6 +1441,7 @@ static void fwnet_init_dev(struct net_device *net)
|
|||||||
net->hard_header_len = FWNET_HLEN;
|
net->hard_header_len = FWNET_HLEN;
|
||||||
net->type = ARPHRD_IEEE1394;
|
net->type = ARPHRD_IEEE1394;
|
||||||
net->tx_queue_len = FWNET_TX_QUEUE_LEN;
|
net->tx_queue_len = FWNET_TX_QUEUE_LEN;
|
||||||
|
net->ethtool_ops = &fwnet_ethtool_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* caller must hold fwnet_device_mutex */
|
/* caller must hold fwnet_device_mutex */
|
||||||
@@ -1455,6 +1482,8 @@ static int fwnet_add_peer(struct fwnet_device *dev,
|
|||||||
|
|
||||||
spin_lock_irq(&dev->lock);
|
spin_lock_irq(&dev->lock);
|
||||||
list_add_tail(&peer->peer_link, &dev->peer_list);
|
list_add_tail(&peer->peer_link, &dev->peer_list);
|
||||||
|
dev->peer_count++;
|
||||||
|
set_carrier_state(dev);
|
||||||
spin_unlock_irq(&dev->lock);
|
spin_unlock_irq(&dev->lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1535,13 +1564,15 @@ static int fwnet_probe(struct device *_dev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fwnet_remove_peer(struct fwnet_peer *peer)
|
static void fwnet_remove_peer(struct fwnet_peer *peer, struct fwnet_device *dev)
|
||||||
{
|
{
|
||||||
struct fwnet_partial_datagram *pd, *pd_next;
|
struct fwnet_partial_datagram *pd, *pd_next;
|
||||||
|
|
||||||
spin_lock_irq(&peer->dev->lock);
|
spin_lock_irq(&dev->lock);
|
||||||
list_del(&peer->peer_link);
|
list_del(&peer->peer_link);
|
||||||
spin_unlock_irq(&peer->dev->lock);
|
dev->peer_count--;
|
||||||
|
set_carrier_state(dev);
|
||||||
|
spin_unlock_irq(&dev->lock);
|
||||||
|
|
||||||
list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link)
|
list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link)
|
||||||
fwnet_pd_delete(pd);
|
fwnet_pd_delete(pd);
|
||||||
@@ -1558,7 +1589,7 @@ static int fwnet_remove(struct device *_dev)
|
|||||||
|
|
||||||
mutex_lock(&fwnet_device_mutex);
|
mutex_lock(&fwnet_device_mutex);
|
||||||
|
|
||||||
fwnet_remove_peer(peer);
|
fwnet_remove_peer(peer, dev);
|
||||||
|
|
||||||
if (list_empty(&dev->peer_list)) {
|
if (list_empty(&dev->peer_list)) {
|
||||||
net = dev->netdev;
|
net = dev->netdev;
|
||||||
|
@@ -302,7 +302,7 @@ nosy_open(struct inode *inode, struct file *file)
|
|||||||
|
|
||||||
file->private_data = client;
|
file->private_data = client;
|
||||||
|
|
||||||
return 0;
|
return nonseekable_open(inode, file);
|
||||||
fail:
|
fail:
|
||||||
kfree(client);
|
kfree(client);
|
||||||
lynx_put(lynx);
|
lynx_put(lynx);
|
||||||
@@ -405,7 +405,6 @@ static const struct file_operations nosy_ops = {
|
|||||||
.poll = nosy_poll,
|
.poll = nosy_poll,
|
||||||
.open = nosy_open,
|
.open = nosy_open,
|
||||||
.release = nosy_release,
|
.release = nosy_release,
|
||||||
.llseek = noop_llseek,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */
|
#define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -302,9 +302,9 @@ struct fw_packet {
|
|||||||
struct fw_transaction {
|
struct fw_transaction {
|
||||||
int node_id; /* The generation is implied; it is always the current. */
|
int node_id; /* The generation is implied; it is always the current. */
|
||||||
int tlabel;
|
int tlabel;
|
||||||
int timestamp;
|
|
||||||
struct list_head link;
|
struct list_head link;
|
||||||
struct fw_card *card;
|
struct fw_card *card;
|
||||||
|
bool is_split_transaction;
|
||||||
struct timer_list split_timeout_timer;
|
struct timer_list split_timeout_timer;
|
||||||
|
|
||||||
struct fw_packet packet;
|
struct fw_packet packet;
|
||||||
|
Reference in New Issue
Block a user