#include <linux/idr.h>
#include <linux/rwsem.h>
#include <asm/semaphore.h>
+#include <asm/system.h>
#include <linux/ctype.h>
#include "fw-transaction.h"
#include "fw-topology.h"
}
static int
-fw_unit_uevent(struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct fw_unit *unit = fw_unit(dev);
char modalias[64];
- int length = 0;
- int i = 0;
get_modalias(unit, modalias, sizeof(modalias));
- if (add_uevent_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "MODALIAS=%s", modalias))
+ if (add_uevent_var(env, "MODALIAS=%s", modalias))
return -ENOMEM;
- envp[i] = NULL;
-
return 0;
}
int fw_device_enable_phys_dma(struct fw_device *device)
{
+ int generation = device->generation;
+
+ /* device->node_id, accessed below, must not be older than generation */
+ smp_rmb();
+
return device->card->driver->enable_phys_dma(device->card,
device->node_id,
- device->generation);
+ generation);
}
EXPORT_SYMBOL(fw_device_enable_phys_dma);
complete(&callback_data->done);
}
-static int read_rom(struct fw_device *device, int index, u32 * data)
+static int
+read_rom(struct fw_device *device, int generation, int index, u32 *data)
{
struct read_quadlet_callback_data callback_data;
struct fw_transaction t;
u64 offset;
+ /* device->node_id, accessed below, must not be older than generation */
+ smp_rmb();
+
init_completion(&callback_data.done);
offset = 0xfffff0000400ULL + index * 4;
fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
- device->node_id,
- device->generation, SCODE_100,
+ device->node_id, generation, device->max_speed,
offset, NULL, 4, complete_transaction, &callback_data);
wait_for_completion(&callback_data.done);
return callback_data.rcode;
}
-static int read_bus_info_block(struct fw_device *device)
+/*
+ * Read the bus info block, perform a speed probe, and read all of the rest of
+ * the config ROM. We do all this with a cached bus generation. If the bus
+ * generation changes under us, read_bus_info_block will fail and get retried.
+ * It's better to start all over in this case because the node from which we
+ * are reading the ROM may have changed the ROM during the reset.
+ */
+static int read_bus_info_block(struct fw_device *device, int generation)
{
static u32 rom[256];
u32 stack[16], sp, key;
int i, end, length;
+ device->max_speed = SCODE_100;
+
/* First read the bus info block. */
for (i = 0; i < 5; i++) {
- if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
+ if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
return -1;
/*
* As per IEEE1212 7.2, during power-up, devices can
return -1;
}
+ device->max_speed = device->node->max_speed;
+
+ /*
+ * Determine the speed of
+ * - devices with link speed less than PHY speed,
+ * - devices with 1394b PHY (unless only connected to 1394a PHYs),
+ * - all devices if there are 1394b repeaters.
+ * Note, we cannot use the bus info block's link_spd as starting point
+ * because some buggy firmwares set it lower than necessary and because
+ * 1394-1995 nodes do not have the field.
+ */
+ if ((rom[2] & 0x7) < device->max_speed ||
+ device->max_speed == SCODE_BETA ||
+ device->card->beta_repeaters_present) {
+ u32 dummy;
+
+ /* for S1600 and S3200 */
+ if (device->max_speed == SCODE_BETA)
+ device->max_speed = device->card->link_speed;
+
+ while (device->max_speed > SCODE_100) {
+ if (read_rom(device, generation, 0, &dummy) ==
+ RCODE_COMPLETE)
+ break;
+ device->max_speed--;
+ }
+ }
+
/*
* Now parse the config rom. The config rom is a recursive
* directory structure so we parse it using a stack of
return -1;
/* Read header quadlet for the block to get the length. */
- if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
+ if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
return -1;
end = i + (rom[i] >> 16) + 1;
i++;
* it references another block, and push it in that case.
*/
while (i < end) {
- if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
+ if (read_rom(device, generation, i, &rom[i]) !=
+ RCODE_COMPLETE)
return -1;
if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
sp < ARRAY_SIZE(stack))
* device.
*/
- if (read_bus_info_block(device) < 0) {
+ if (read_bus_info_block(device, device->generation) < 0) {
if (device->config_rom_retries < MAX_RETRIES) {
device->config_rom_retries++;
schedule_delayed_work(&device->work, RETRY_DELAY);
FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
fw_device_shutdown(&device->work.work);
else
- fw_notify("created new fw device %s (%d config rom retries)\n",
- device->device.bus_id, device->config_rom_retries);
+ fw_notify("created new fw device %s "
+ "(%d config rom retries, S%d00)\n",
+ device->device.bus_id, device->config_rom_retries,
+ 1 << device->max_speed);
/*
* Reschedule the IRM work if we just finished reading the
device = node->data;
device->node_id = node->node_id;
+ smp_wmb(); /* update node_id before generation */
device->generation = card->generation;
if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {
PREPARE_DELAYED_WORK(&device->work, fw_device_update);