aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/aoe/aoecmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/aoe/aoecmd.c')
-rw-r--r--drivers/block/aoe/aoecmd.c117
1 files changed, 83 insertions, 34 deletions
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 1be5150bcd3b..b49e06ef121e 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -106,45 +106,104 @@ ifrotate(struct aoetgt *t)
106 } 106 }
107} 107}
108 108
109static void
110skb_pool_put(struct aoedev *d, struct sk_buff *skb)
111{
112 if (!d->skbpool_hd)
113 d->skbpool_hd = skb;
114 else
115 d->skbpool_tl->next = skb;
116 d->skbpool_tl = skb;
117}
118
119static struct sk_buff *
120skb_pool_get(struct aoedev *d)
121{
122 struct sk_buff *skb;
123
124 skb = d->skbpool_hd;
125 if (skb && atomic_read(&skb_shinfo(skb)->dataref) == 1) {
126 d->skbpool_hd = skb->next;
127 skb->next = NULL;
128 return skb;
129 }
130 if (d->nskbpool < NSKBPOOLMAX
131 && (skb = new_skb(ETH_ZLEN))) {
132 d->nskbpool++;
133 return skb;
134 }
135 return NULL;
136}
137
138/* freeframe is where we do our load balancing so it's a little hairy. */
109static struct frame * 139static struct frame *
110freeframe(struct aoedev *d) 140freeframe(struct aoedev *d)
111{ 141{
112 struct frame *f, *e; 142 struct frame *f, *e, *rf;
113 struct aoetgt **t; 143 struct aoetgt **t;
114 ulong n; 144 struct sk_buff *skb;
115 145
116 if (d->targets[0] == NULL) { /* shouldn't happen, but I'm paranoid */ 146 if (d->targets[0] == NULL) { /* shouldn't happen, but I'm paranoid */
117 printk(KERN_ERR "aoe: NULL TARGETS!\n"); 147 printk(KERN_ERR "aoe: NULL TARGETS!\n");
118 return NULL; 148 return NULL;
119 } 149 }
120 t = d->targets; 150 t = d->tgt;
121 do { 151 t++;
122 if (t != d->htgt 152 if (t >= &d->targets[NTARGETS] || !*t)
123 && (*t)->ifp->nd 153 t = d->targets;
124 && (*t)->nout < (*t)->maxout) { 154 for (;;) {
125 n = (*t)->nframes; 155 if ((*t)->nout < (*t)->maxout
156 && t != d->htgt
157 && (*t)->ifp->nd) {
158 rf = NULL;
126 f = (*t)->frames; 159 f = (*t)->frames;
127 e = f + n; 160 e = f + (*t)->nframes;
128 for (; f < e; f++) { 161 for (; f < e; f++) {
129 if (f->tag != FREETAG) 162 if (f->tag != FREETAG)
130 continue; 163 continue;
131 if (atomic_read(&skb_shinfo(f->skb)->dataref) 164 skb = f->skb;
165 if (!skb
166 && !(f->skb = skb = new_skb(ETH_ZLEN)))
167 continue;
168 if (atomic_read(&skb_shinfo(skb)->dataref)
132 != 1) { 169 != 1) {
133 n--; 170 if (!rf)
171 rf = f;
134 continue; 172 continue;
135 } 173 }
136 skb_shinfo(f->skb)->nr_frags = 0; 174gotone: skb_shinfo(skb)->nr_frags = skb->data_len = 0;
137 f->skb->data_len = 0; 175 skb_trim(skb, 0);
138 skb_trim(f->skb, 0);
139 d->tgt = t; 176 d->tgt = t;
140 ifrotate(*t); 177 ifrotate(*t);
141 return f; 178 return f;
142 } 179 }
143 if (n == 0) /* slow polling network card */ 180 /* Work can be done, but the network layer is
181 holding our precious packets. Try to grab
182 one from the pool. */
183 f = rf;
184 if (f == NULL) { /* more paranoia */
185 printk(KERN_ERR
186 "aoe: freeframe: %s.\n",
187 "unexpected null rf");
188 d->flags |= DEVFL_KICKME;
189 return NULL;
190 }
191 skb = skb_pool_get(d);
192 if (skb) {
193 skb_pool_put(d, f->skb);
194 f->skb = skb;
195 goto gotone;
196 }
197 (*t)->dataref++;
198 if ((*t)->nout == 0)
144 d->flags |= DEVFL_KICKME; 199 d->flags |= DEVFL_KICKME;
145 } 200 }
201 if (t == d->tgt) /* we've looped and found nada */
202 break;
146 t++; 203 t++;
147 } while (t < &d->targets[NTARGETS] && *t); 204 if (t >= &d->targets[NTARGETS] || !*t)
205 t = d->targets;
206 }
148 return NULL; 207 return NULL;
149} 208}
150 209
@@ -894,33 +953,23 @@ addtgt(struct aoedev *d, char *addr, ulong nframes)
894 return NULL; 953 return NULL;
895 954
896 t = kcalloc(1, sizeof *t, GFP_ATOMIC); 955 t = kcalloc(1, sizeof *t, GFP_ATOMIC);
956 if (!t)
957 return NULL;
897 f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); 958 f = kcalloc(nframes, sizeof *f, GFP_ATOMIC);
898 if (!t || !f) 959 if (!f) {
899 goto bail; 960 kfree(t);
961 return NULL;
962 }
963
900 t->nframes = nframes; 964 t->nframes = nframes;
901 t->frames = f; 965 t->frames = f;
902 e = f + nframes; 966 e = f + nframes;
903 for (; f < e; f++) { 967 for (; f < e; f++)
904 f->tag = FREETAG; 968 f->tag = FREETAG;
905 f->skb = new_skb(ETH_ZLEN);
906 if (!f->skb)
907 break;
908 }
909 if (f != e) {
910 while (f > t->frames) {
911 f--;
912 dev_kfree_skb(f->skb);
913 }
914 goto bail;
915 }
916 memcpy(t->addr, addr, sizeof t->addr); 969 memcpy(t->addr, addr, sizeof t->addr);
917 t->ifp = t->ifs; 970 t->ifp = t->ifs;
918 t->maxout = t->nframes; 971 t->maxout = t->nframes;
919 return *tt = t; 972 return *tt = t;
920bail:
921 kfree(t);
922 kfree(f);
923 return NULL;
924} 973}
925 974
926void 975void