#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/timer.h>
+#include <linux/jiffies.h>
#include "csr1212.h"
#include "ieee1394.h"
#include "config_roms.h"
-static void delayed_reset_bus(unsigned long __reset_info)
+static void delayed_reset_bus(void * __reset_info)
{
struct hpsb_host *host = (struct hpsb_host*)__reset_info;
int generation = host->csr.generation + 1;
static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p)
{
- return 0;
+ return 0;
}
static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg)
{
- return -1;
+ return -1;
}
static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg)
}
static struct hpsb_host_driver dummy_driver = {
- .transmit_packet = dummy_transmit_packet,
- .devctl = dummy_devctl,
- .isoctl = dummy_isoctl
+ .transmit_packet = dummy_transmit_packet,
+ .devctl = dummy_devctl,
+ .isoctl = dummy_isoctl
};
static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
struct device *dev)
{
- struct hpsb_host *h;
+ struct hpsb_host *h;
int i;
int hostnum = 0;
- h = kmalloc(sizeof(struct hpsb_host) + extra, SLAB_KERNEL);
- if (!h) return NULL;
- memset(h, 0, sizeof(struct hpsb_host) + extra);
+ h = kzalloc(sizeof(*h) + extra, SLAB_KERNEL);
+ if (!h)
+ return NULL;
h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h);
if (!h->csr.rom) {
}
h->hostdata = h + 1;
- h->driver = drv;
+ h->driver = drv;
skb_queue_head_init(&h->pending_packet_queue);
INIT_LIST_HEAD(&h->addr_space);
- init_timer(&h->delayed_reset);
- h->delayed_reset.function = delayed_reset_bus;
- h->delayed_reset.data = (unsigned long)h;
for (i = 2; i < 16; i++)
h->csr.gen_timestamp[i] = jiffies - 60 * HZ;
atomic_set(&h->generation, 0);
+ INIT_WORK(&h->delayed_reset, delayed_reset_bus, h);
+
init_timer(&h->timeout);
h->timeout.data = (unsigned long) h;
h->timeout.function = abort_timedouts;
h->timeout_interval = HZ / 20; // 50ms by default
- h->topology_map = h->csr.topology_map + 3;
- h->speed_map = (u8 *)(h->csr.speed_map + 2);
+ h->topology_map = h->csr.topology_map + 3;
+ h->speed_map = (u8 *)(h->csr.speed_map + 2);
down(&host_num_alloc);
void hpsb_remove_host(struct hpsb_host *host)
{
- host->is_shutdown = 1;
- host->driver = &dummy_driver;
+ host->is_shutdown = 1;
+
+ cancel_delayed_work(&host->delayed_reset);
+ flush_scheduled_work();
+
+ host->driver = &dummy_driver;
- highlevel_remove_host(host);
+ highlevel_remove_host(host);
hpsb_remove_extra_config_roms(host);
int hpsb_update_config_rom_image(struct hpsb_host *host)
{
- unsigned long reset_time;
+ unsigned long reset_delay;
int next_gen = host->csr.generation + 1;
if (!host->update_config_rom)
/* Stop the delayed interrupt, we're about to change the config rom and
* it would be a waste to do a bus reset twice. */
- del_timer_sync(&host->delayed_reset);
+ cancel_delayed_work(&host->delayed_reset);
/* IEEE 1394a-2000 prohibits using the same generation number
* twice in a 60 second period. */
- if (jiffies - host->csr.gen_timestamp[next_gen] < 60 * HZ)
+ if (time_before(jiffies, host->csr.gen_timestamp[next_gen] + 60 * HZ))
/* Wait 60 seconds from the last time this generation number was
* used. */
- reset_time = (60 * HZ) + host->csr.gen_timestamp[next_gen];
+ reset_delay = (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies;
else
/* Wait 1 second in case some other code wants to change the
* Config ROM in the near future. */
- reset_time = jiffies + HZ;
+ reset_delay = HZ;
- /* This will add the timer as well as modify it */
- mod_timer(&host->delayed_reset, reset_time);
+ PREPARE_WORK(&host->delayed_reset, delayed_reset_bus, host);
+ schedule_delayed_work(&host->delayed_reset, reset_delay);
return 0;
}