diff options
Diffstat (limited to 'drivers/ieee1394')
-rw-r--r-- | drivers/ieee1394/csr1212.c | 57 | ||||
-rw-r--r-- | drivers/ieee1394/csr1212.h | 6 | ||||
-rw-r--r-- | drivers/ieee1394/eth1394.c | 16 | ||||
-rw-r--r-- | drivers/ieee1394/ieee1394_core.c | 2 | ||||
-rw-r--r-- | drivers/ieee1394/nodemgr.c | 22 | ||||
-rw-r--r-- | drivers/ieee1394/pcilynx.c | 29 | ||||
-rw-r--r-- | drivers/ieee1394/sbp2.c | 15 |
7 files changed, 73 insertions, 74 deletions
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c index d08166b..e8122de 100644 --- a/drivers/ieee1394/csr1212.c +++ b/drivers/ieee1394/csr1212.c @@ -218,12 +218,10 @@ static struct csr1212_keyval *csr1212_new_keyval(u8 type, u8 key) if (!kv) return NULL; + atomic_set(&kv->refcnt, 1); kv->key.type = type; kv->key.id = key; - kv->associate = NULL; - kv->refcnt = 1; - kv->next = NULL; kv->prev = NULL; kv->offset = 0; @@ -326,12 +324,13 @@ void csr1212_associate_keyval(struct csr1212_keyval *kv, if (kv->associate) csr1212_release_keyval(kv->associate); - associate->refcnt++; + csr1212_keep_keyval(associate); kv->associate = associate; } -int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, - struct csr1212_keyval *kv) +static int __csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, + struct csr1212_keyval *kv, + bool keep_keyval) { struct csr1212_dentry *dentry; @@ -341,10 +340,10 @@ int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, if (!dentry) return -ENOMEM; + if (keep_keyval) + csr1212_keep_keyval(kv); dentry->kv = kv; - kv->refcnt++; - dentry->next = NULL; dentry->prev = dir->value.directory.dentries_tail; @@ -358,6 +357,12 @@ int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, return CSR1212_SUCCESS; } +int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, + struct csr1212_keyval *kv) +{ + return __csr1212_attach_keyval_to_directory(dir, kv, true); +} + #define CSR1212_DESCRIPTOR_LEAF_DATA(kv) \ (&((kv)->value.leaf.data[1])) @@ -483,15 +488,18 @@ void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir, /* This function is used to free the memory taken by a keyval. If the given * keyval is a directory type, then any keyvals contained in that directory - * will be destroyed as well if their respective refcnts are 0. By means of + * will be destroyed as well if noone holds a reference on them. By means of * list manipulation, this routine will descend a directory structure in a * non-recursive manner. */ -static void csr1212_destroy_keyval(struct csr1212_keyval *kv) +void csr1212_release_keyval(struct csr1212_keyval *kv) { struct csr1212_keyval *k, *a; struct csr1212_dentry dentry; struct csr1212_dentry *head, *tail; + if (!atomic_dec_and_test(&kv->refcnt)) + return; + dentry.kv = kv; dentry.next = NULL; dentry.prev = NULL; @@ -503,9 +511,8 @@ static void csr1212_destroy_keyval(struct csr1212_keyval *kv) k = head->kv; while (k) { - k->refcnt--; - - if (k->refcnt > 0) + /* must not dec_and_test kv->refcnt again */ + if (k != kv && !atomic_dec_and_test(&k->refcnt)) break; a = k->associate; @@ -536,14 +543,6 @@ static void csr1212_destroy_keyval(struct csr1212_keyval *kv) } } -void csr1212_release_keyval(struct csr1212_keyval *kv) -{ - if (kv->refcnt > 1) - kv->refcnt--; - else - csr1212_destroy_keyval(kv); -} - void csr1212_destroy_csr(struct csr1212_csr *csr) { struct csr1212_csr_rom_cache *c, *oc; @@ -1126,6 +1125,7 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos) int ret = CSR1212_SUCCESS; struct csr1212_keyval *k = NULL; u32 offset; + bool keep_keyval = true; switch (CSR1212_KV_KEY_TYPE(ki)) { case CSR1212_KV_TYPE_IMMEDIATE: @@ -1135,8 +1135,8 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos) ret = -ENOMEM; goto out; } - - k->refcnt = 0; /* Don't keep local reference when parsing. */ + /* Don't keep local reference when parsing. */ + keep_keyval = false; break; case CSR1212_KV_TYPE_CSR_OFFSET: @@ -1146,7 +1146,8 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos) ret = -ENOMEM; goto out; } - k->refcnt = 0; /* Don't keep local reference when parsing. */ + /* Don't keep local reference when parsing. */ + keep_keyval = false; break; default: @@ -1174,8 +1175,10 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos) ret = -ENOMEM; goto out; } - k->refcnt = 0; /* Don't keep local reference when parsing. */ - k->valid = 0; /* Contents not read yet so it's not valid. */ + /* Don't keep local reference when parsing. */ + keep_keyval = false; + /* Contents not read yet so it's not valid. */ + k->valid = 0; k->offset = offset; k->prev = dir; @@ -1183,7 +1186,7 @@ csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos) dir->next->prev = k; dir->next = k; } - ret = csr1212_attach_keyval_to_directory(dir, k); + ret = __csr1212_attach_keyval_to_directory(dir, k, keep_keyval); out: if (ret != CSR1212_SUCCESS && k != NULL) free_keyval(k); diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h index df909ce..043039f 100644 --- a/drivers/ieee1394/csr1212.h +++ b/drivers/ieee1394/csr1212.h @@ -32,6 +32,7 @@ #include <linux/types.h> #include <linux/slab.h> +#include <asm/atomic.h> #define CSR1212_MALLOC(size) kmalloc((size), GFP_KERNEL) #define CSR1212_FREE(ptr) kfree(ptr) @@ -149,7 +150,7 @@ struct csr1212_keyval { struct csr1212_directory directory; } value; struct csr1212_keyval *associate; - int refcnt; + atomic_t refcnt; /* used in generating and/or parsing CSR image */ struct csr1212_keyval *next, *prev; /* flat list of CSR elements */ @@ -350,7 +351,8 @@ csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv); * need for code to retain a keyval that has been parsed. */ static inline void csr1212_keep_keyval(struct csr1212_keyval *kv) { - kv->refcnt++; + atomic_inc(&kv->refcnt); + smp_mb__after_atomic_inc(); } diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index dc9dce2..b166b35 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -1153,8 +1153,6 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid, pdg->sz++; lh = find_partial_datagram(pdgl, dgl); } else { - struct partial_datagram *pd; - pd = list_entry(lh, struct partial_datagram, list); if (fragment_overlap(&pd->frag_info, fg_off, fg_len)) { @@ -1222,23 +1220,19 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid, priv->stats.rx_errors++; priv->stats.rx_dropped++; dev_kfree_skb_any(skb); - goto bad_proto; - } - - if (netif_rx(skb) == NET_RX_DROP) { + } else if (netif_rx(skb) == NET_RX_DROP) { priv->stats.rx_errors++; priv->stats.rx_dropped++; - goto bad_proto; + } else { + priv->stats.rx_packets++; + priv->stats.rx_bytes += skb->len; } - /* Statistics */ - priv->stats.rx_packets++; - priv->stats.rx_bytes += skb->len; + spin_unlock_irqrestore(&priv->lock, flags); bad_proto: if (netif_queue_stopped(dev)) netif_wake_queue(dev); - spin_unlock_irqrestore(&priv->lock, flags); dev->last_rx = jiffies; diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index 98fd985..36c747b 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -488,7 +488,7 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot) highlevel_host_reset(host); } -static spinlock_t pending_packets_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(pending_packets_lock); /** * hpsb_packet_sent - notify core of sending a packet diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 1939fee..90dc75b 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -1014,13 +1014,13 @@ static struct unit_directory *nodemgr_process_unit_directory CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) { switch (last_key_id) { case CSR1212_KV_ID_VENDOR: - ud->vendor_name_kv = kv; csr1212_keep_keyval(kv); + ud->vendor_name_kv = kv; break; case CSR1212_KV_ID_MODEL: - ud->model_name_kv = kv; csr1212_keep_keyval(kv); + ud->model_name_kv = kv; break; } @@ -1112,7 +1112,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent { unsigned int ud_id = 0; struct csr1212_dentry *dentry; - struct csr1212_keyval *kv; + struct csr1212_keyval *kv, *vendor_name_kv = NULL; u8 last_key_id = 0; ne->needs_probe = 0; @@ -1139,8 +1139,8 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 && CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 && CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) { - ne->vendor_name_kv = kv; csr1212_keep_keyval(kv); + vendor_name_kv = kv; } } break; @@ -1149,10 +1149,13 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent } if (ne->vendor_name_kv) { - int error = device_create_file(&ne->device, - &dev_attr_ne_vendor_name_kv); - - if (error && error != -EEXIST) + kv = ne->vendor_name_kv; + ne->vendor_name_kv = vendor_name_kv; + csr1212_release_keyval(kv); + } else if (vendor_name_kv) { + ne->vendor_name_kv = vendor_name_kv; + if (device_create_file(&ne->device, + &dev_attr_ne_vendor_name_kv) != 0) HPSB_ERR("Failed to add sysfs attribute"); } } @@ -1712,7 +1715,8 @@ static int nodemgr_host_thread(void *__hi) * to make sure things settle down. */ g = get_hpsb_generation(host); for (i = 0; i < 4 ; i++) { - if (msleep_interruptible(63) || kthread_should_stop()) + msleep_interruptible(63); + if (kthread_should_stop()) goto exit; /* Now get the generation in which the node ID's we collect diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c index d1a5bcd..8af01ab 100644 --- a/drivers/ieee1394/pcilynx.c +++ b/drivers/ieee1394/pcilynx.c @@ -121,16 +121,6 @@ static int bit_getsda(void *data) return reg_read((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL) & 0x00000010; } -static int bit_reg(struct i2c_client *client) -{ - return 0; -} - -static int bit_unreg(struct i2c_client *client) -{ - return 0; -} - static struct i2c_algo_bit_data bit_data = { .setsda = bit_setsda, .setscl = bit_setscl, @@ -140,14 +130,6 @@ static struct i2c_algo_bit_data bit_data = { .timeout = 100, }; -static struct i2c_adapter bit_ops = { - .id = 0xAA, //FIXME: probably we should get an id in i2c-id.h - .client_register = bit_reg, - .client_unregister = bit_unreg, - .name = "PCILynx I2C", -}; - - /* * PCL handling functions. @@ -765,7 +747,6 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) } else { struct ti_pcl pcl; u32 ack; - struct hpsb_packet *packet; PRINT(KERN_INFO, lynx->id, "cancelling async packet, that was already in PCL"); @@ -1436,9 +1417,11 @@ static int __devinit add_card(struct pci_dev *dev, struct i2c_algo_bit_data i2c_adapter_data; error = -ENOMEM; - i2c_ad = kmemdup(&bit_ops, sizeof(*i2c_ad), GFP_KERNEL); + i2c_ad = kzalloc(sizeof(*i2c_ad), GFP_KERNEL); if (!i2c_ad) FAIL("failed to allocate I2C adapter memory"); + i2c_ad->id = I2C_HW_B_PCILYNX; + strlcpy(i2c_ad->name, "PCILynx I2C", sizeof(i2c_ad->name)); i2c_adapter_data = bit_data; i2c_ad->algo_data = &i2c_adapter_data; i2c_adapter_data.data = lynx; @@ -1465,13 +1448,11 @@ static int __devinit add_card(struct pci_dev *dev, { 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block } }; - /* we use i2c_transfer, because i2c_smbus_read_block_data does not work properly and we - do it more efficiently in one transaction rather then using several reads */ + /* we use i2c_transfer because we have no i2c_client + at hand */ if (i2c_transfer(i2c_ad, msg, 2) < 0) { PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c"); } else { - int i; - PRINT(KERN_INFO, lynx->id, "got bus info block from serial eeprom"); /* FIXME: probably we shoud rewrite the max_rec, max_ROM(1394a), * generation(1394a) and link_spd(1394a) field and recalculate diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index a81ba8f..1b353b9 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -242,6 +242,8 @@ static int sbp2_max_speed_and_size(struct sbp2_lu *); static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC }; +static DEFINE_RWLOCK(sbp2_hi_logical_units_lock); + static struct hpsb_highlevel sbp2_highlevel = { .name = SBP2_DEVICE_NAME, .host_reset = sbp2_host_reset, @@ -732,6 +734,7 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) struct sbp2_fwhost_info *hi; struct Scsi_Host *shost = NULL; struct sbp2_lu *lu = NULL; + unsigned long flags; lu = kzalloc(sizeof(*lu), GFP_KERNEL); if (!lu) { @@ -784,7 +787,9 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) lu->hi = hi; + write_lock_irqsave(&sbp2_hi_logical_units_lock, flags); list_add_tail(&lu->lu_list, &hi->logical_units); + write_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags); /* Register the status FIFO address range. We could use the same FIFO * for targets at different nodes. However we need different FIFOs per @@ -828,16 +833,20 @@ static void sbp2_host_reset(struct hpsb_host *host) { struct sbp2_fwhost_info *hi; struct sbp2_lu *lu; + unsigned long flags; hi = hpsb_get_hostinfo(&sbp2_highlevel, host); if (!hi) return; + + read_lock_irqsave(&sbp2_hi_logical_units_lock, flags); list_for_each_entry(lu, &hi->logical_units, lu_list) if (likely(atomic_read(&lu->state) != SBP2LU_STATE_IN_SHUTDOWN)) { atomic_set(&lu->state, SBP2LU_STATE_IN_RESET); scsi_block_requests(lu->shost); } + read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags); } static int sbp2_start_device(struct sbp2_lu *lu) @@ -919,6 +928,7 @@ alloc_fail: static void sbp2_remove_device(struct sbp2_lu *lu) { struct sbp2_fwhost_info *hi; + unsigned long flags; if (!lu) return; @@ -933,7 +943,9 @@ static void sbp2_remove_device(struct sbp2_lu *lu) flush_scheduled_work(); sbp2util_remove_command_orb_pool(lu, hi->host); + write_lock_irqsave(&sbp2_hi_logical_units_lock, flags); list_del(&lu->lu_list); + write_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags); if (lu->login_response) dma_free_coherent(hi->host->device.parent, @@ -1707,6 +1719,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, } /* Find the unit which wrote the status. */ + read_lock_irqsave(&sbp2_hi_logical_units_lock, flags); list_for_each_entry(lu_tmp, &hi->logical_units, lu_list) { if (lu_tmp->ne->nodeid == nodeid && lu_tmp->status_fifo_addr == addr) { @@ -1714,6 +1727,8 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, break; } } + read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags); + if (unlikely(!lu)) { SBP2_ERR("lu is NULL - device is gone?"); return RCODE_ADDRESS_ERROR; |