Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07117e30 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://bedivere.hansenpartnership.com/git/scsi-rc-fixes-2.6:
  [SCSI] 3w-9xxx: fix iommu_iova leak
  [SCSI] cxgb3i: convert cdev->l2opt to use rcu to prevent NULL dereference
  [SCSI] scsi: qla4xxx needs libiscsi.o
  [SCSI] libsas: fix failure to revalidate domain for anything but the first expander child.
  [SCSI] aacraid: reset should disable MSI interrupt
parents c54a06d4 96067723
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -287,7 +287,7 @@ void __free_ep(struct kref *kref)
	if (test_bit(RELEASE_RESOURCES, &ep->com.flags)) {
		cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid);
		dst_release(ep->dst);
		l2t_release(L2DATA(ep->com.tdev), ep->l2t);
		l2t_release(ep->com.tdev, ep->l2t);
	}
	kfree(ep);
}
@@ -1178,7 +1178,7 @@ static int act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
		release_tid(ep->com.tdev, GET_TID(rpl), NULL);
	cxgb3_free_atid(ep->com.tdev, ep->atid);
	dst_release(ep->dst);
	l2t_release(L2DATA(ep->com.tdev), ep->l2t);
	l2t_release(ep->com.tdev, ep->l2t);
	put_ep(&ep->com);
	return CPL_RET_BUF_DONE;
}
@@ -1377,7 +1377,7 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
	if (!child_ep) {
		printk(KERN_ERR MOD "%s - failed to allocate ep entry!\n",
		       __func__);
		l2t_release(L2DATA(tdev), l2t);
		l2t_release(tdev, l2t);
		dst_release(dst);
		goto reject;
	}
@@ -1956,7 +1956,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
	if (!err)
		goto out;

	l2t_release(L2DATA(h->rdev.t3cdev_p), ep->l2t);
	l2t_release(h->rdev.t3cdev_p, ep->l2t);
fail4:
	dst_release(ep->dst);
fail3:
@@ -2127,7 +2127,7 @@ int iwch_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new,
	PDBG("%s ep %p redirect to dst %p l2t %p\n", __func__, ep, new,
	     l2t);
	dst_hold(new);
	l2t_release(L2DATA(ep->com.tdev), ep->l2t);
	l2t_release(ep->com.tdev, ep->l2t);
	ep->l2t = l2t;
	dst_release(old);
	ep->dst = new;
+18 −5
Original line number Diff line number Diff line
@@ -1146,12 +1146,14 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
		if (te && te->ctx && te->client && te->client->redirect) {
			update_tcb = te->client->redirect(te->ctx, old, new, e);
			if (update_tcb) {
				rcu_read_lock();
				l2t_hold(L2DATA(tdev), e);
				rcu_read_unlock();
				set_l2t_ix(tdev, tid, e);
			}
		}
	}
	l2t_release(L2DATA(tdev), e);
	l2t_release(tdev, e);
}

/*
@@ -1264,7 +1266,7 @@ int cxgb3_offload_activate(struct adapter *adapter)
		goto out_free;

	err = -ENOMEM;
	L2DATA(dev) = t3_init_l2t(l2t_capacity);
	RCU_INIT_POINTER(dev->l2opt, t3_init_l2t(l2t_capacity));
	if (!L2DATA(dev))
		goto out_free;

@@ -1298,16 +1300,24 @@ int cxgb3_offload_activate(struct adapter *adapter)

out_free_l2t:
	t3_free_l2t(L2DATA(dev));
	L2DATA(dev) = NULL;
	rcu_assign_pointer(dev->l2opt, NULL);
out_free:
	kfree(t);
	return err;
}

static void clean_l2_data(struct rcu_head *head)
{
	struct l2t_data *d = container_of(head, struct l2t_data, rcu_head);
	t3_free_l2t(d);
}


void cxgb3_offload_deactivate(struct adapter *adapter)
{
	struct t3cdev *tdev = &adapter->tdev;
	struct t3c_data *t = T3C_DATA(tdev);
	struct l2t_data *d;

	remove_adapter(adapter);
	if (list_empty(&adapter_list))
@@ -1315,8 +1325,11 @@ void cxgb3_offload_deactivate(struct adapter *adapter)

	free_tid_maps(&t->tid_maps);
	T3C_DATA(tdev) = NULL;
	t3_free_l2t(L2DATA(tdev));
	L2DATA(tdev) = NULL;
	rcu_read_lock();
	d = L2DATA(tdev);
	rcu_read_unlock();
	rcu_assign_pointer(tdev->l2opt, NULL);
	call_rcu(&d->rcu_head, clean_l2_data);
	if (t->nofail_skb)
		kfree_skb(t->nofail_skb);
	kfree(t);
+12 −3
Original line number Diff line number Diff line
@@ -300,14 +300,21 @@ static inline void reuse_entry(struct l2t_entry *e, struct neighbour *neigh)
struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh,
			     struct net_device *dev)
{
	struct l2t_entry *e;
	struct l2t_data *d = L2DATA(cdev);
	struct l2t_entry *e = NULL;
	struct l2t_data *d;
	int hash;
	u32 addr = *(u32 *) neigh->primary_key;
	int ifidx = neigh->dev->ifindex;
	int hash = arp_hash(addr, ifidx, d);
	struct port_info *p = netdev_priv(dev);
	int smt_idx = p->port_id;

	rcu_read_lock();
	d = L2DATA(cdev);
	if (!d)
		goto done_rcu;

	hash = arp_hash(addr, ifidx, d);

	write_lock_bh(&d->lock);
	for (e = d->l2tab[hash].first; e; e = e->next)
		if (e->addr == addr && e->ifindex == ifidx &&
@@ -338,6 +345,8 @@ struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh,
	}
done:
	write_unlock_bh(&d->lock);
done_rcu:
	rcu_read_unlock();
	return e;
}

+12 −4
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ struct l2t_data {
	atomic_t nfree;		/* number of free entries */
	rwlock_t lock;
	struct l2t_entry l2tab[0];
	struct rcu_head rcu_head;	/* to handle rcu cleanup */
};

typedef void (*arp_failure_handler_func)(struct t3cdev * dev,
@@ -99,7 +100,7 @@ static inline void set_arp_failure_handler(struct sk_buff *skb,
/*
 * Getting to the L2 data from an offload device.
 */
#define L2DATA(dev) ((dev)->l2opt)
#define L2DATA(cdev) (rcu_dereference((cdev)->l2opt))

#define W_TCB_L2T_IX    0
#define S_TCB_L2T_IX    7
@@ -126,15 +127,22 @@ static inline int l2t_send(struct t3cdev *dev, struct sk_buff *skb,
	return t3_l2t_send_slow(dev, skb, e);
}

static inline void l2t_release(struct l2t_data *d, struct l2t_entry *e)
static inline void l2t_release(struct t3cdev *t, struct l2t_entry *e)
{
	if (atomic_dec_and_test(&e->refcnt))
	struct l2t_data *d;

	rcu_read_lock();
	d = L2DATA(t);

	if (atomic_dec_and_test(&e->refcnt) && d)
		t3_l2e_free(d, e);

	rcu_read_unlock();
}

static inline void l2t_hold(struct l2t_data *d, struct l2t_entry *e)
{
	if (atomic_add_return(1, &e->refcnt) == 1)	/* 0 -> 1 transition */
	if (d && atomic_add_return(1, &e->refcnt) == 1)	/* 0 -> 1 transition */
		atomic_dec(&d->nfree);
}

+2 −0
Original line number Diff line number Diff line
@@ -1800,10 +1800,12 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
	switch (retval) {
	case SCSI_MLQUEUE_HOST_BUSY:
		twa_free_request_id(tw_dev, request_id);
		twa_unmap_scsi_data(tw_dev, request_id);
		break;
	case 1:
		tw_dev->state[request_id] = TW_S_COMPLETED;
		twa_free_request_id(tw_dev, request_id);
		twa_unmap_scsi_data(tw_dev, request_id);
		SCpnt->result = (DID_ERROR << 16);
		done(SCpnt);
		retval = 0;
Loading